<commit_before>//! A "tiny" example of HTTP request/response handling using just tokio-core
//!
//! This example is intended for *learning purposes* to see how various pieces
//! hook up together and how HTTP can get up and running. Note that this example
//! is written with the restriction that it *can't* use any "big" library other
//! than tokio-core, if you'd like a "real world" HTTP library you likely want a
//! crate like Hyper.
//!
//! Code here is based on the `echo-threads` example and implements two paths,
//! the `/plaintext` and `/json` routes to respond with some text and json,
//! respectively. By default this will run I/O on all the cores your system has
//! available, and it doesn't support HTTP request bodies.

#![deny(warnings)]

extern crate bytes;
extern crate http;
extern crate httparse;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate time;
extern crate tokio;
extern crate tokio_io;

use std::{env, fmt, io};
use std::net::SocketAddr;

use tokio::net::{TcpStream, TcpListener};
use tokio::prelude::*;
use tokio::codec::{Encoder, Decoder};

use bytes::BytesMut;
use http::header::HeaderValue;
use http::{Request, Response, StatusCode};

fn main() -> Result<(), Box<std::error::Error>> {
    // Parse the arguments, bind the TCP socket we'll be listening to, spin up
    // our worker threads, and start shipping sockets to those worker threads.
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>()?;

    let listener = TcpListener::bind(&addr)?;
    println!("Listening on: {}", addr);

    tokio::run({
        listener.incoming()
            .map_err(|e| println!("failed to accept socket; error = {:?}", e))
            .for_each(|socket| {
                process(socket);
                Ok(())
            })
    });
    Ok(())
}

fn process(socket: TcpStream) {
    let (tx, rx) =
        // Frame the socket using the `Http` protocol. This maps the TCP socket
        // to a Stream + Sink of HTTP frames.
        Http.framed(socket)
        // This splits a single `Stream + Sink` value into two separate handles
        // that can be used independently (even on different tasks or threads).
        .split();

    // Map all requests into responses and send them back to the client.
    let task = tx.send_all(rx.and_then(respond))
        .then(|res| {
            if let Err(e) = res {
                println!("failed to process connection; error = {:?}", e);
            }

            Ok(())
        });

    // Spawn the task that handles the connection.
    tokio::spawn(task);
}

/// "Server logic" is implemented in this function.
///
/// This function is a map from and HTTP request to a future of a response and
/// represents the various handling a server might do. Currently the contents
/// here are pretty uninteresting.
fn respond(req: Request<()>)
    -> Box<Future<Item = Response<String>, Error = io::Error> + Send>
{
    let f = future::lazy(move || {
        let mut response = Response::builder();
        let body = match req.uri().path() {
            "/plaintext" => {
                response.header("Content-Type", "text/plain");
                "Hello, World!".to_string()
            }
            "/json" => {
                response.header("Content-Type", "application/json");

                #[derive(Serialize)]
                struct Message {
                    message: &'static str,
                }
                serde_json::to_string(&Message { message: "Hello, World!" })?
            }
            _ => {
                response.status(StatusCode::NOT_FOUND);
                String::new()
            }
        };
        let response = response.body(body).map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
        Ok(response)
    });

    Box::new(f)
}

struct Http;

/// Implementation of encoding an HTTP response into a `BytesMut`, basically
/// just writing out an HTTP/1.1 response.
impl Encoder for Http {
    type Item = Response<String>;
    type Error = io::Error;

    fn encode(&mut self, item: Response<String>, dst: &mut BytesMut) -> io::Result<()> {
        use std::fmt::Write;

        write!(BytesWrite(dst), "\
            HTTP/1.1 {}\r\n\
            Server: Example\r\n\
            Content-Length: {}\r\n\
            Date: {}\r\n\
        ", item.status(), item.body().len(), date::now()).unwrap();

        for (k, v) in item.headers() {
            dst.extend_from_slice(k.as_str().as_bytes());
            dst.extend_from_slice(b": ");
            dst.extend_from_slice(v.as_bytes());
            dst.extend_from_slice(b"\r\n");
        }

        dst.extend_from_slice(b"\r\n");
        dst.extend_from_slice(item.body().as_bytes());

        return Ok(());

        // Right now `write!` on `Vec<u8>` goes through io::Write and is not
        // super speedy, so inline a less-crufty implementation here which
        // doesn't go through io::Error.
        struct BytesWrite<'a>(&'a mut BytesMut);

        impl<'a> fmt::Write for BytesWrite<'a> {
            fn write_str(&mut self, s: &str) -> fmt::Result {
                self.0.extend_from_slice(s.as_bytes());
                Ok(())
            }

            fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
                fmt::write(self, args)
            }
        }
    }
}

/// Implementation of decoding an HTTP request from the bytes we've read so far.
/// This leverages the `httparse` crate to do the actual parsing and then we use
/// that information to construct an instance of a `http::Request` object,
/// trying to avoid allocations where possible.
impl Decoder for Http {
    type Item = Request<()>;
    type Error = io::Error;

    fn decode(&mut self, src: &mut BytesMut) -> io::Result<Option<Request<()>>> {
        // TODO: we should grow this headers array if parsing fails and asks
        //       for more headers
        let mut headers = [None; 16];
        let (method, path, version, amt) = {
            let mut parsed_headers = [httparse::EMPTY_HEADER; 16];
            let mut r = httparse::Request::new(&mut parsed_headers);
            let status = r.parse(src).map_err(|e| {
                let msg = format!("failed to parse http request: {:?}", e);
                io::Error::new(io::ErrorKind::Other, msg)
            })?;

            let amt = match status {
                httparse::Status::Complete(amt) => amt,
                httparse::Status::Partial => return Ok(None),
            };

            let toslice = |a: &[u8]| {
                let start = a.as_ptr() as usize - src.as_ptr() as usize;
                assert!(start < src.len());
                (start, start + a.len())
            };

            for (i, header) in r.headers.iter().enumerate() {
                let k = toslice(header.name.as_bytes());
                let v = toslice(header.value);
                headers[i] = Some((k, v));
            }

            (toslice(r.method.unwrap().as_bytes()),
             toslice(r.path.unwrap().as_bytes()),
             r.version.unwrap(),
             amt)
        };
        if version != 1 {
            return Err(io::Error::new(io::ErrorKind::Other, "only HTTP/1.1 accepted"))
        }
        let data = src.split_to(amt).freeze();
        let mut ret = Request::builder();
        ret.method(&data[method.0..method.1]);
        ret.uri(data.slice(path.0, path.1));
        ret.version(http::Version::HTTP_11);
        for header in headers.iter() {
            let (k, v) = match *header {
                Some((ref k, ref v)) => (k, v),
                None => break,
            };
            let value = unsafe {
                HeaderValue::from_shared_unchecked(data.slice(v.0, v.1))
            };
            ret.header(&data[k.0..k.1], value);
        }

        let req = ret.body(()).map_err(|e| {
            io::Error::new(io::ErrorKind::Other, e)
        })?;
        Ok(Some(req))
    }
}

mod date {
    use std::cell::RefCell;
    use std::fmt::{self, Write};
    use std::str;

    use time::{self, Duration};

    pub struct Now(());

    /// Returns a struct, which when formatted, renders an appropriate `Date`
    /// header value.
    pub fn now() -> Now {
        Now(())
    }

    // Gee Alex, doesn't this seem like premature optimization. Well you see
    // there Billy, you're absolutely correct! If your server is *bottlenecked*
    // on rendering the `Date` header, well then boy do I have news for you, you
    // don't need this optimization.
    //
    // In all seriousness, though, a simple "hello world" benchmark which just
    // sends back literally "hello world" with standard headers actually is
    // bottlenecked on rendering a date into a byte buffer. Since it was at the
    // top of a profile, and this was done for some competitive benchmarks, this
    // module was written.
    //
    // Just to be clear, though, I was not intending on doing this because it
    // really does seem kinda absurd, but it was done by someone else [1], so I
    // blame them!  :)
    //
    // [1]: https://github.com/rapidoid/rapidoid/blob/f1c55c0555007e986b5d069fe1086e6d09933f7b/rapidoid-commons/src/main/java/org/rapidoid/commons/Dates.java#L48-L66

    struct LastRenderedNow {
        bytes: [u8; 128],
        amt: usize,
        next_update: time::Timespec,
    }

    thread_local!(static LAST: RefCell<LastRenderedNow> = RefCell::new(LastRenderedNow {
        bytes: [0; 128],
        amt: 0,
        next_update: time::Timespec::new(0, 0),
    }));

    impl fmt::Display for Now {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            LAST.with(|cache| {
                let mut cache = cache.borrow_mut();
                let now = time::get_time();
                if now >= cache.next_update {
                    cache.update(now);
                }
                f.write_str(cache.buffer())
            })
        }
    }

    impl LastRenderedNow {
        fn buffer(&self) -> &str {
            str::from_utf8(&self.bytes[..self.amt]).unwrap()
        }

        fn update(&mut self, now: time::Timespec) {
            self.amt = 0;
            write!(LocalBuffer(self), "{}", time::at(now).rfc822()).unwrap();
            self.next_update = now + Duration::seconds(1);
            self.next_update.nsec = 0;
        }
    }

    struct LocalBuffer<'a>(&'a mut LastRenderedNow);

    impl<'a> fmt::Write for LocalBuffer<'a> {
        fn write_str(&mut self, s: &str) -> fmt::Result {
            let start = self.0.amt;
            let end = start + s.len();
            self.0.bytes[start..end].copy_from_slice(s.as_bytes());
            self.0.amt += s.len();
            Ok(())
        }
    }
}
<commit_msg>examples: remove reference to tokio-core (#780)<commit_after>//! A "tiny" example of HTTP request/response handling using transports.
//!
//! This example is intended for *learning purposes* to see how various pieces
//! hook up together and how HTTP can get up and running. Note that this example
//! is written with the restriction that it *can't* use any "big" library other
//! than Tokio, if you'd like a "real world" HTTP library you likely want a
//! crate like Hyper.
//!
//! Code here is based on the `echo-threads` example and implements two paths,
//! the `/plaintext` and `/json` routes to respond with some text and json,
//! respectively. By default this will run I/O on all the cores your system has
//! available, and it doesn't support HTTP request bodies.

#![deny(warnings)]

extern crate bytes;
extern crate http;
extern crate httparse;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate time;
extern crate tokio;
extern crate tokio_io;

use std::{env, fmt, io};
use std::net::SocketAddr;

use tokio::net::{TcpStream, TcpListener};
use tokio::prelude::*;
use tokio::codec::{Encoder, Decoder};

use bytes::BytesMut;
use http::header::HeaderValue;
use http::{Request, Response, StatusCode};

fn main() -> Result<(), Box<std::error::Error>> {
    // Parse the arguments, bind the TCP socket we'll be listening to, spin up
    // our worker threads, and start shipping sockets to those worker threads.
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>()?;

    let listener = TcpListener::bind(&addr)?;
    println!("Listening on: {}", addr);

    tokio::run({
        listener.incoming()
            .map_err(|e| println!("failed to accept socket; error = {:?}", e))
            .for_each(|socket| {
                process(socket);
                Ok(())
            })
    });
    Ok(())
}

fn process(socket: TcpStream) {
    let (tx, rx) =
        // Frame the socket using the `Http` protocol. This maps the TCP socket
        // to a Stream + Sink of HTTP frames.
        Http.framed(socket)
        // This splits a single `Stream + Sink` value into two separate handles
        // that can be used independently (even on different tasks or threads).
        .split();

    // Map all requests into responses and send them back to the client.
    let task = tx.send_all(rx.and_then(respond))
        .then(|res| {
            if let Err(e) = res {
                println!("failed to process connection; error = {:?}", e);
            }

            Ok(())
        });

    // Spawn the task that handles the connection.
    tokio::spawn(task);
}

/// "Server logic" is implemented in this function.
///
/// This function is a map from and HTTP request to a future of a response and
/// represents the various handling a server might do. Currently the contents
/// here are pretty uninteresting.
fn respond(req: Request<()>)
    -> Box<Future<Item = Response<String>, Error = io::Error> + Send>
{
    let f = future::lazy(move || {
        let mut response = Response::builder();
        let body = match req.uri().path() {
            "/plaintext" => {
                response.header("Content-Type", "text/plain");
                "Hello, World!".to_string()
            }
            "/json" => {
                response.header("Content-Type", "application/json");

                #[derive(Serialize)]
                struct Message {
                    message: &'static str,
                }
                serde_json::to_string(&Message { message: "Hello, World!" })?
            }
            _ => {
                response.status(StatusCode::NOT_FOUND);
                String::new()
            }
        };
        let response = response.body(body).map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
        Ok(response)
    });

    Box::new(f)
}

struct Http;

/// Implementation of encoding an HTTP response into a `BytesMut`, basically
/// just writing out an HTTP/1.1 response.
impl Encoder for Http {
    type Item = Response<String>;
    type Error = io::Error;

    fn encode(&mut self, item: Response<String>, dst: &mut BytesMut) -> io::Result<()> {
        use std::fmt::Write;

        write!(BytesWrite(dst), "\
            HTTP/1.1 {}\r\n\
            Server: Example\r\n\
            Content-Length: {}\r\n\
            Date: {}\r\n\
        ", item.status(), item.body().len(), date::now()).unwrap();

        for (k, v) in item.headers() {
            dst.extend_from_slice(k.as_str().as_bytes());
            dst.extend_from_slice(b": ");
            dst.extend_from_slice(v.as_bytes());
            dst.extend_from_slice(b"\r\n");
        }

        dst.extend_from_slice(b"\r\n");
        dst.extend_from_slice(item.body().as_bytes());

        return Ok(());

        // Right now `write!` on `Vec<u8>` goes through io::Write and is not
        // super speedy, so inline a less-crufty implementation here which
        // doesn't go through io::Error.
        struct BytesWrite<'a>(&'a mut BytesMut);

        impl<'a> fmt::Write for BytesWrite<'a> {
            fn write_str(&mut self, s: &str) -> fmt::Result {
                self.0.extend_from_slice(s.as_bytes());
                Ok(())
            }

            fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
                fmt::write(self, args)
            }
        }
    }
}

/// Implementation of decoding an HTTP request from the bytes we've read so far.
/// This leverages the `httparse` crate to do the actual parsing and then we use
/// that information to construct an instance of a `http::Request` object,
/// trying to avoid allocations where possible.
impl Decoder for Http {
    type Item = Request<()>;
    type Error = io::Error;

    fn decode(&mut self, src: &mut BytesMut) -> io::Result<Option<Request<()>>> {
        // TODO: we should grow this headers array if parsing fails and asks
        //       for more headers
        let mut headers = [None; 16];
        let (method, path, version, amt) = {
            let mut parsed_headers = [httparse::EMPTY_HEADER; 16];
            let mut r = httparse::Request::new(&mut parsed_headers);
            let status = r.parse(src).map_err(|e| {
                let msg = format!("failed to parse http request: {:?}", e);
                io::Error::new(io::ErrorKind::Other, msg)
            })?;

            let amt = match status {
                httparse::Status::Complete(amt) => amt,
                httparse::Status::Partial => return Ok(None),
            };

            let toslice = |a: &[u8]| {
                let start = a.as_ptr() as usize - src.as_ptr() as usize;
                assert!(start < src.len());
                (start, start + a.len())
            };

            for (i, header) in r.headers.iter().enumerate() {
                let k = toslice(header.name.as_bytes());
                let v = toslice(header.value);
                headers[i] = Some((k, v));
            }

            (toslice(r.method.unwrap().as_bytes()),
             toslice(r.path.unwrap().as_bytes()),
             r.version.unwrap(),
             amt)
        };
        if version != 1 {
            return Err(io::Error::new(io::ErrorKind::Other, "only HTTP/1.1 accepted"))
        }
        let data = src.split_to(amt).freeze();
        let mut ret = Request::builder();
        ret.method(&data[method.0..method.1]);
        ret.uri(data.slice(path.0, path.1));
        ret.version(http::Version::HTTP_11);
        for header in headers.iter() {
            let (k, v) = match *header {
                Some((ref k, ref v)) => (k, v),
                None => break,
            };
            let value = unsafe {
                HeaderValue::from_shared_unchecked(data.slice(v.0, v.1))
            };
            ret.header(&data[k.0..k.1], value);
        }

        let req = ret.body(()).map_err(|e| {
            io::Error::new(io::ErrorKind::Other, e)
        })?;
        Ok(Some(req))
    }
}

mod date {
    use std::cell::RefCell;
    use std::fmt::{self, Write};
    use std::str;

    use time::{self, Duration};

    pub struct Now(());

    /// Returns a struct, which when formatted, renders an appropriate `Date`
    /// header value.
    pub fn now() -> Now {
        Now(())
    }

    // Gee Alex, doesn't this seem like premature optimization. Well you see
    // there Billy, you're absolutely correct! If your server is *bottlenecked*
    // on rendering the `Date` header, well then boy do I have news for you, you
    // don't need this optimization.
    //
    // In all seriousness, though, a simple "hello world" benchmark which just
    // sends back literally "hello world" with standard headers actually is
    // bottlenecked on rendering a date into a byte buffer. Since it was at the
    // top of a profile, and this was done for some competitive benchmarks, this
    // module was written.
    //
    // Just to be clear, though, I was not intending on doing this because it
    // really does seem kinda absurd, but it was done by someone else [1], so I
    // blame them!  :)
    //
    // [1]: https://github.com/rapidoid/rapidoid/blob/f1c55c0555007e986b5d069fe1086e6d09933f7b/rapidoid-commons/src/main/java/org/rapidoid/commons/Dates.java#L48-L66

    struct LastRenderedNow {
        bytes: [u8; 128],
        amt: usize,
        next_update: time::Timespec,
    }

    thread_local!(static LAST: RefCell<LastRenderedNow> = RefCell::new(LastRenderedNow {
        bytes: [0; 128],
        amt: 0,
        next_update: time::Timespec::new(0, 0),
    }));

    impl fmt::Display for Now {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            LAST.with(|cache| {
                let mut cache = cache.borrow_mut();
                let now = time::get_time();
                if now >= cache.next_update {
                    cache.update(now);
                }
                f.write_str(cache.buffer())
            })
        }
    }

    impl LastRenderedNow {
        fn buffer(&self) -> &str {
            str::from_utf8(&self.bytes[..self.amt]).unwrap()
        }

        fn update(&mut self, now: time::Timespec) {
            self.amt = 0;
            write!(LocalBuffer(self), "{}", time::at(now).rfc822()).unwrap();
            self.next_update = now + Duration::seconds(1);
            self.next_update.nsec = 0;
        }
    }

    struct LocalBuffer<'a>(&'a mut LastRenderedNow);

    impl<'a> fmt::Write for LocalBuffer<'a> {
        fn write_str(&mut self, s: &str) -> fmt::Result {
            let start = self.0.amt;
            let end = start + s.len();
            self.0.bytes[start..end].copy_from_slice(s.as_bytes());
            self.0.amt += s.len();
            Ok(())
        }
    }
}
<|endoftext|>


<commit_before>extern crate nalgebra as na;
extern crate ncollide3d;
extern crate nphysics3d;
extern crate nphysics_testbed3d;

use na::{Isometry3, Point3, Vector3};
use ncollide3d::shape::{Cuboid, ShapeHandle};
use nphysics3d::object::{BodyHandle, Material};
use nphysics3d::volumetric::Volumetric;
use nphysics3d::world::World;
use nphysics_testbed3d::Testbed;

const COLLIDER_MARGIN: f32 = 0.01;

fn main() {
    /*
     * World
     */
    let mut world = World::new();
    world.set_gravity(Vector3::new(0.0, -9.81, 0.0));

    /*
     * Ground.
     */
    let ground_size = 50.0;
    let ground_shape =
        ShapeHandle::new(Cuboid::new(Vector3::repeat(ground_size - COLLIDER_MARGIN)));
    let ground_pos = Isometry3::new(Vector3::y() * -ground_size, na::zero());

    world.add_collider(
        COLLIDER_MARGIN,
        ground_shape,
        BodyHandle::ground(),
        ground_pos,
        Material::default(),
    );

    /*
     * Create the boxes
     */
    let num = 10;
    let rad = 0.1;
    let shift = rad * 2.0;
    let centerx = shift * (num as f32) / 2.0;
    let centery = shift / 2.0;
    let centerz = shift * (num as f32) / 2.0;
    let height = 2.0; // 3.0;

    let geom = ShapeHandle::new(Cuboid::new(Vector3::repeat(rad - COLLIDER_MARGIN)));
    let inertia = geom.inertia(1.0);
    let center_of_mass = geom.center_of_mass();

    for i in 0usize..num {
        for j in 0usize..num {
            for k in 0usize..num {
                let x = i as f32 * shift - centerx;
                let y = j as f32 * shift + centery + height;
                let z = k as f32 * shift - centerz;

                /*
                 * Create the rigid body.
                 */
                let pos = Isometry3::new(Vector3::new(x, y, z), na::zero());
                let handle = world.add_rigid_body(pos, inertia, center_of_mass);

                /*
                 * Create the collider.
                 */
                world.add_collider(
                    COLLIDER_MARGIN,
                    geom.clone(),
                    handle,
                    Isometry3::identity(),
                    Material::default(),
                );
            }
        }
    }

    /*
     * Set up the testbed.
     */
    let mut testbed = Testbed::new(world);
    // testbed.hide_performance_counters();
    testbed.look_at(Point3::new(-4.0, 1.0, -4.0), Point3::new(0.0, 1.0, 0.0));
    testbed.run();
}
<commit_msg>Reset the number of boxes on the boxes3 demos to its old value.<commit_after>extern crate nalgebra as na;
extern crate ncollide3d;
extern crate nphysics3d;
extern crate nphysics_testbed3d;

use na::{Isometry3, Point3, Vector3};
use ncollide3d::shape::{Cuboid, ShapeHandle};
use nphysics3d::object::{BodyHandle, Material};
use nphysics3d::volumetric::Volumetric;
use nphysics3d::world::World;
use nphysics_testbed3d::Testbed;

const COLLIDER_MARGIN: f32 = 0.01;

fn main() {
    /*
     * World
     */
    let mut world = World::new();
    world.set_gravity(Vector3::new(0.0, -9.81, 0.0));

    /*
     * Ground.
     */
    let ground_size = 50.0;
    let ground_shape =
        ShapeHandle::new(Cuboid::new(Vector3::repeat(ground_size - COLLIDER_MARGIN)));
    let ground_pos = Isometry3::new(Vector3::y() * -ground_size, na::zero());

    world.add_collider(
        COLLIDER_MARGIN,
        ground_shape,
        BodyHandle::ground(),
        ground_pos,
        Material::default(),
    );

    /*
     * Create the boxes
     */
    let num = 7;
    let rad = 0.1;
    let shift = rad * 2.0;
    let centerx = shift * (num as f32) / 2.0;
    let centery = shift / 2.0;
    let centerz = shift * (num as f32) / 2.0;
    let height = 2.0; // 3.0;

    let geom = ShapeHandle::new(Cuboid::new(Vector3::repeat(rad - COLLIDER_MARGIN)));
    let inertia = geom.inertia(1.0);
    let center_of_mass = geom.center_of_mass();

    for i in 0usize..num {
        for j in 0usize..num {
            for k in 0usize..num {
                let x = i as f32 * shift - centerx;
                let y = j as f32 * shift + centery + height;
                let z = k as f32 * shift - centerz;

                /*
                 * Create the rigid body.
                 */
                let pos = Isometry3::new(Vector3::new(x, y, z), na::zero());
                let handle = world.add_rigid_body(pos, inertia, center_of_mass);

                /*
                 * Create the collider.
                 */
                world.add_collider(
                    COLLIDER_MARGIN,
                    geom.clone(),
                    handle,
                    Isometry3::identity(),
                    Material::default(),
                );
            }
        }
    }

    /*
     * Set up the testbed.
     */
    let mut testbed = Testbed::new(world);
    // testbed.hide_performance_counters();
    testbed.look_at(Point3::new(-4.0, 1.0, -4.0), Point3::new(0.0, 1.0, 0.0));
    testbed.run();
}
<|endoftext|>


<commit_before>use proc_macro2::TokenStream;
use quote::ToTokens;
use std::collections::btree_map::Entry;
use std::collections::{BTreeMap as Map, BTreeSet as Set};
use syn::punctuated::Punctuated;
use syn::{parse_quote, GenericArgument, Generics, Ident, PathArguments, Token, Type, WhereClause};

pub struct ParamsInScope<'a> {
    names: Set<&'a Ident>,
}

impl<'a> ParamsInScope<'a> {
    pub fn new(generics: &'a Generics) -> Self {
        ParamsInScope {
            names: generics.type_params().map(|param| &param.ident).collect(),
        }
    }

    pub fn intersects(&self, ty: &Type) -> bool {
        let mut found = false;
        crawl(self, ty, &mut found);
        found
    }
}

fn crawl(in_scope: &ParamsInScope, ty: &Type, found: &mut bool) {
    if let Type::Path(ty) = ty {
        if ty.qself.is_none() {
            if let Some(ident) = ty.path.get_ident() {
                if in_scope.names.contains(ident) {
                    *found = true;
                }
            }
        }
        for segment in &ty.path.segments {
            if let PathArguments::AngleBracketed(arguments) = &segment.arguments {
                for arg in &arguments.args {
                    if let GenericArgument::Type(ty) = arg {
                        crawl(in_scope, ty, found);
                    }
                }
            }
        }
    }
}

pub struct InferredBounds {
    bounds: Map<String, (Set<String>, Punctuated<TokenStream, Token![+]>)>,
    order: Vec<TokenStream>,
}

impl InferredBounds {
    pub fn new() -> Self {
        InferredBounds {
            bounds: Map::new(),
            order: Vec::new(),
        }
    }

    pub fn insert(&mut self, ty: impl ToTokens, bound: impl ToTokens) {
        let ty = ty.to_token_stream();
        let bound = bound.to_token_stream();
        let entry = self.bounds.entry(ty.to_string());
        if let Entry::Vacant(_) = entry {
            self.order.push(ty);
        }
        let (set, tokens) = entry.or_default();
        if set.insert(bound.to_string()) {
            tokens.push(bound);
        }
    }

    pub fn augment_where_clause(&self, generics: &Generics) -> WhereClause {
        let mut generics = generics.clone();
        let where_clause = generics.make_where_clause();
        for ty in &self.order {
            let (_set, bounds) = &self.bounds[&ty.to_string()];
            where_clause.predicates.push(parse_quote!(#ty: #bounds));
        }
        generics.where_clause.unwrap()
    }
}
<commit_msg>Ignore type_repetition_in_bounds/trait_duplication_in_bounds clippy false positive<commit_after>use proc_macro2::TokenStream;
use quote::ToTokens;
use std::collections::btree_map::Entry;
use std::collections::{BTreeMap as Map, BTreeSet as Set};
use syn::punctuated::Punctuated;
use syn::{parse_quote, GenericArgument, Generics, Ident, PathArguments, Token, Type, WhereClause};

pub struct ParamsInScope<'a> {
    names: Set<&'a Ident>,
}

impl<'a> ParamsInScope<'a> {
    pub fn new(generics: &'a Generics) -> Self {
        ParamsInScope {
            names: generics.type_params().map(|param| &param.ident).collect(),
        }
    }

    pub fn intersects(&self, ty: &Type) -> bool {
        let mut found = false;
        crawl(self, ty, &mut found);
        found
    }
}

fn crawl(in_scope: &ParamsInScope, ty: &Type, found: &mut bool) {
    if let Type::Path(ty) = ty {
        if ty.qself.is_none() {
            if let Some(ident) = ty.path.get_ident() {
                if in_scope.names.contains(ident) {
                    *found = true;
                }
            }
        }
        for segment in &ty.path.segments {
            if let PathArguments::AngleBracketed(arguments) = &segment.arguments {
                for arg in &arguments.args {
                    if let GenericArgument::Type(ty) = arg {
                        crawl(in_scope, ty, found);
                    }
                }
            }
        }
    }
}

pub struct InferredBounds {
    bounds: Map<String, (Set<String>, Punctuated<TokenStream, Token![+]>)>,
    order: Vec<TokenStream>,
}

impl InferredBounds {
    pub fn new() -> Self {
        InferredBounds {
            bounds: Map::new(),
            order: Vec::new(),
        }
    }

    #[allow(clippy::type_repetition_in_bounds, clippy::trait_duplication_in_bounds)] // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8771
    pub fn insert(&mut self, ty: impl ToTokens, bound: impl ToTokens) {
        let ty = ty.to_token_stream();
        let bound = bound.to_token_stream();
        let entry = self.bounds.entry(ty.to_string());
        if let Entry::Vacant(_) = entry {
            self.order.push(ty);
        }
        let (set, tokens) = entry.or_default();
        if set.insert(bound.to_string()) {
            tokens.push(bound);
        }
    }

    pub fn augment_where_clause(&self, generics: &Generics) -> WhereClause {
        let mut generics = generics.clone();
        let where_clause = generics.make_where_clause();
        for ty in &self.order {
            let (_set, bounds) = &self.bounds[&ty.to_string()];
            where_clause.predicates.push(parse_quote!(#ty: #bounds));
        }
        generics.where_clause.unwrap()
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![feature(globs)]
#![crate_name = "cube"]

extern crate piston;
// extern crate glfw_game_window;
extern crate sdl2_game_window;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate native;
extern crate time;

// use glfw_game_window::GameWindowGLFW as Window;
use sdl2_game_window::GameWindowSDL2 as Window;
use gfx::{Device, DeviceHelper};
use piston::{cam, GameWindow};
//----------------------------------------
// Cube associated data

#[vertex_format]
struct Vertex {
    #[as_float]
    a_Pos: [i8, ..3],
    #[as_float]
    a_TexCoord: [u8, ..2],
}

impl Vertex {
    fn new(pos: [i8, ..3], tc: [u8, ..2]) -> Vertex {
        Vertex {
            a_Pos: pos,
            a_TexCoord: tc,
        }
    }
}

#[shader_param(Program)]
struct Params {
    u_ModelViewProj: [[f32, ..4], ..4],
    t_Color: gfx::shade::TextureParam,
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    attribute vec3 a_Pos;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;
    uniform mat4 u_ModelViewProj;
    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_ModelViewProj * vec4(a_Pos, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec3 a_Pos;
    in vec2 a_TexCoord;
    out vec2 v_TexCoord;
    uniform mat4 u_ModelViewProj;
    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_ModelViewProj * vec4(a_Pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    varying vec2 v_TexCoord;
    uniform sampler2D t_Color;
    void main() {
        vec4 tex = texture2D(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec2 v_TexCoord;
    out vec4 o_Color;
    uniform sampler2D t_Color;
    void main() {
        vec4 tex = texture(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
};

//----------------------------------------

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let mut window = Window::new(
        piston::shader_version::opengl::OpenGL_3_2,
        piston::GameWindowSettings {
            title: "cube".to_string(),
            size: [640, 480],
            fullscreen: false,
            exit_on_esc: true
        }
    );

    window.capture_cursor(true);

    let (mut device, frame) = window.gfx();
    let mut renderer = device.create_renderer();
    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        //top (0, 0, 1)
        Vertex::new([-1, -1,  1], [0, 0]),
        Vertex::new([ 1, -1,  1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //bottom (0, 0, -1)
        Vertex::new([ 1,  1, -1], [0, 0]),
        Vertex::new([-1,  1, -1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
        //right (1, 0, 0)
        Vertex::new([ 1, -1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([ 1, -1,  1], [0, 1]),
        //left (-1, 0, 0)
        Vertex::new([-1,  1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([-1,  1, -1], [0, 1]),
        //front (0, 1, 0)
        Vertex::new([-1,  1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //back (0, -1, 0)
        Vertex::new([ 1, -1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
    ];

    let mesh = device.create_mesh(vertex_data);

    let slice = {
        let index_data = vec![
            0u8, 1, 2, 2, 3, 0,    //top
            4, 5, 6, 6, 7, 4,       //bottom
            8, 9, 10, 10, 11, 8,    //right
            12, 13, 14, 14, 16, 12, //left
            16, 17, 18, 18, 19, 16, //front
            20, 21, 22, 22, 23, 20, //back
        ];

        let buf = device.create_buffer_static(&index_data);
        gfx::IndexSlice8(gfx::TriangleList, buf, 0, 36)
    };

    let tinfo = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let img_info = tinfo.to_image_info();
    let texture = device.create_texture(tinfo).unwrap();
    device.update_texture(
            &texture,
            &img_info,
            &vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8]
        ).unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(
            gfx::tex::Bilinear,
            gfx::tex::Clamp
        )
    );

    let mut data = Params {
        u_ModelViewProj: piston::vecmath::mat4_id(),
        t_Color: (texture, Some(sampler)),
    };
    let prog: Program = device.link_program(
            VERTEX_SRC.clone(),
            FRAGMENT_SRC.clone()
        ).unwrap();

    let model = piston::vecmath::mat4_id();
    let projection = cam::CameraPerspective {
            fov: 90.0f32,
            near_clip: 0.1,
            far_clip: 1000.0,
            aspect_ratio: 1.0
        }.projection();
    let mut camera = cam::Camera::new(0.5f32, 0.5, 4.0);
    let mut fps_controller = cam::FPSController::new(
        cam::FPSControllerSettings::default()
    );
    camera.set_yaw_pitch(fps_controller.yaw, fps_controller.pitch);

    let mut game_iter = piston::GameIterator::new(
        &mut window,
        &piston::GameIteratorSettings {
            updates_per_second: 120,
            max_frames_per_second: 60
        }
    );

    for e in game_iter {
        match e {
            piston::Render(_args) => {
                renderer.reset();
                renderer.clear(
                    gfx::ClearData {
                        color: Some([0.3, 0.3, 0.3, 1.0]),
                        depth: Some(1.0),
                        stencil: None,
                    },
                    &frame
                );
                data.u_ModelViewProj = cam::model_view_projection(
                        model,
                        camera.orthogonal(),
                        projection
                    );
                renderer.draw(&mesh, slice, &frame, (&prog, &data), &state).unwrap();
                device.submit(renderer.as_buffer());
            },
            piston::Update(args) => fps_controller.update(args.dt, &mut camera),
            piston::Input(e) => fps_controller.input(&e, &mut camera),
        }
    }
}

<commit_msg>Upgraded to latest Piston<commit_after>#![feature(phase)]
#![feature(globs)]
#![crate_name = "cube"]

extern crate piston;
// extern crate glfw_game_window;
extern crate sdl2_game_window;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate native;
extern crate time;

// use glfw_game_window::GameWindowGLFW as Window;
use sdl2_game_window::GameWindowSDL2 as Window;
use gfx::{Device, DeviceHelper};
use piston::{cam, GameWindow};
//----------------------------------------
// Cube associated data

#[vertex_format]
struct Vertex {
    #[as_float]
    a_Pos: [i8, ..3],
    #[as_float]
    a_TexCoord: [u8, ..2],
}

impl Vertex {
    fn new(pos: [i8, ..3], tc: [u8, ..2]) -> Vertex {
        Vertex {
            a_Pos: pos,
            a_TexCoord: tc,
        }
    }
}

#[shader_param(Program)]
struct Params {
    u_ModelViewProj: [[f32, ..4], ..4],
    t_Color: gfx::shade::TextureParam,
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    attribute vec3 a_Pos;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;
    uniform mat4 u_ModelViewProj;
    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_ModelViewProj * vec4(a_Pos, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec3 a_Pos;
    in vec2 a_TexCoord;
    out vec2 v_TexCoord;
    uniform mat4 u_ModelViewProj;
    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_ModelViewProj * vec4(a_Pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    varying vec2 v_TexCoord;
    uniform sampler2D t_Color;
    void main() {
        vec4 tex = texture2D(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec2 v_TexCoord;
    out vec4 o_Color;
    uniform sampler2D t_Color;
    void main() {
        vec4 tex = texture(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
};

//----------------------------------------

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let mut window = Window::new(
        piston::shader_version::opengl::OpenGL_3_2,
        piston::GameWindowSettings {
            title: "cube".to_string(),
            size: [640, 480],
            fullscreen: false,
            exit_on_esc: true
        }
    );

    window.capture_cursor(true);

    let (mut device, frame) = window.gfx();
    let mut renderer = device.create_renderer();
    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        //top (0, 0, 1)
        Vertex::new([-1, -1,  1], [0, 0]),
        Vertex::new([ 1, -1,  1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //bottom (0, 0, -1)
        Vertex::new([ 1,  1, -1], [0, 0]),
        Vertex::new([-1,  1, -1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
        //right (1, 0, 0)
        Vertex::new([ 1, -1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([ 1, -1,  1], [0, 1]),
        //left (-1, 0, 0)
        Vertex::new([-1,  1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([-1,  1, -1], [0, 1]),
        //front (0, 1, 0)
        Vertex::new([-1,  1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //back (0, -1, 0)
        Vertex::new([ 1, -1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
    ];

    let mesh = device.create_mesh(vertex_data);

    let slice = {
        let index_data = vec![
            0u8, 1, 2, 2, 3, 0,    //top
            4, 5, 6, 6, 7, 4,       //bottom
            8, 9, 10, 10, 11, 8,    //right
            12, 13, 14, 14, 16, 12, //left
            16, 17, 18, 18, 19, 16, //front
            20, 21, 22, 22, 23, 20, //back
        ];

        let buf = device.create_buffer_static(&index_data);
        gfx::IndexSlice8(gfx::TriangleList, buf, 0, 36)
    };

    let tinfo = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let img_info = tinfo.to_image_info();
    let texture = device.create_texture(tinfo).unwrap();
    device.update_texture(
            &texture,
            &img_info,
            &vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8]
        ).unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(
            gfx::tex::Bilinear,
            gfx::tex::Clamp
        )
    );

    let mut data = Params {
        u_ModelViewProj: piston::vecmath::mat4_id(),
        t_Color: (texture, Some(sampler)),
    };
    let prog: Program = device.link_program(
            VERTEX_SRC.clone(),
            FRAGMENT_SRC.clone()
        ).unwrap();

    let model = piston::vecmath::mat4_id();
    let projection = cam::CameraPerspective {
            fov: 90.0f32,
            near_clip: 0.1,
            far_clip: 1000.0,
            aspect_ratio: 1.0
        }.projection();
    let mut first_person = cam::FirstPerson::new(
        0.5f32, 0.5, 4.0,
        cam::FirstPersonSettings::default()
    );

    let mut game_iter = piston::GameIterator::new(
        &mut window,
        &piston::GameIteratorSettings {
            updates_per_second: 120,
            max_frames_per_second: 60
        }
    );

    for e in game_iter {
        match e {
            piston::Render(args) => {
                renderer.reset();
                renderer.clear(
                    gfx::ClearData {
                        color: Some([0.3, 0.3, 0.3, 1.0]),
                        depth: Some(1.0),
                        stencil: None,
                    },
                    &frame
                );
                data.u_ModelViewProj = cam::model_view_projection(
                        model,
                        first_person.camera(args.ext_dt).orthogonal(),
                        projection
                    );
                renderer.draw(&mesh, slice, &frame, (&prog, &data), &state).unwrap();
                device.submit(renderer.as_buffer());
            },
            piston::Update(args) => first_person.update(args.dt),
            piston::Input(e) => first_person.input(&e),
        }
    }
}

<|endoftext|>


<commit_before>//! This module provides a microfacet model for transmission (a BTDF), see
//! [Walter et al. 07](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)
//! for details.

use std::f32;
use enum_set::EnumSet;

use linalg::{self, Vector};
use film::Colorf;
use bxdf::{self, BxDF, BxDFType};
use bxdf::fresnel::{Dielectric, Fresnel};
use bxdf::microfacet::{MicrofacetDistribution};

/// Struct providing the microfacet BTDF, implemented as described in
/// [Walter et al. 07](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)
pub struct MicrofacetTransmission {
    reflectance: Colorf,
    fresnel: Dielectric,
    /// Microfacet distribution describing the structure of the microfacets of
    /// the material
    microfacet: Box<MicrofacetDistribution + Send + Sync>,
}

impl MicrofacetTransmission {
    /// Create a new transmissive microfacet BRDF
    pub fn new(c: &Colorf, fresnel: Dielectric,
               microfacet: Box<MicrofacetDistribution + Send + Sync>) -> MicrofacetTransmission {
        MicrofacetTransmission { reflectance: *c, fresnel: fresnel, microfacet: microfacet }
    }
    /// Convenience method for getting `eta_i` and `eta_t` in the right order for if
    /// we're entering or exiting this material based on the direction of the outgoing
    /// ray.
    fn eta_for_interaction(&self, w_o: &Vector) -> (f32, f32) {
        if bxdf::cos_theta(w_o) > 0.0 {
            (self.fresnel.eta_i, self.fresnel.eta_t)
        } else {
            (self.fresnel.eta_t, self.fresnel.eta_i)
        }
    }
    /// Compute the Jacobian for the change of variables (see [Walter et al 07] section 4.2),
    /// here we compute equation 17 in that section.
    fn jacobian(w_o: &Vector, w_i: &Vector, w_h: &Vector, eta: (f32, f32)) -> f32 {
        let wi_dot_h = linalg::dot(w_i, w_h);
        let wo_dot_h = linalg::dot(w_o, w_h);
        f32::powf(eta.1, 2.0) * f32::abs(wo_dot_h) / f32::powf(eta.0 * wi_dot_h + eta.1 * wo_dot_h, 2.0)
    }
    fn half_vector(w_o: &Vector, w_i: &Vector, eta: (f32, f32)) -> Option<Vector> {
        let w_h = -eta.0 * *w_o - eta.1 * *w_i;
        if w_h.x == 0.0 && w_h.y == 0.0 && w_h.z == 0.0 {
            None
        } else {
            Some(w_h.normalized())
        }
    }
}

impl BxDF for MicrofacetTransmission {
    fn bxdf_type(&self) -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Glossy);
        e.insert(BxDFType::Transmission);
        e
    }
    fn eval(&self, w_o: &Vector, w_i: &Vector) -> Colorf {
        if bxdf::same_hemisphere(w_o, w_i) {
            return Colorf::black();
        }
        let cos_to = bxdf::cos_theta(w_o);
        let cos_ti = bxdf::cos_theta(w_i);
        if cos_to == 0.0 || cos_ti == 0.0 {
            return Colorf::black();
        }
        let eta = self.eta_for_interaction(w_o);
        if let Some(w_h) = MicrofacetTransmission::half_vector(w_o, w_i, eta) {
            let d = self.microfacet.normal_distribution(&w_h);
            let f = Colorf::broadcast(1.0) - self.fresnel.fresnel(linalg::dot(w_o, &w_h));
            let g = self.microfacet.shadowing_masking(w_i, w_o, &w_h);
            let wi_dot_h = linalg::dot(w_i, &w_h);
            let jacobian = MicrofacetTransmission::jacobian(w_o, w_i, &w_h, eta);
            self.reflectance * (f32::abs(wi_dot_h) / (f32::abs(w_i.z) * f32::abs(w_o.z)))
                * (f * g * d) * jacobian
        } else {
            Colorf::black()
        }
    }
    fn sample(&self, w_o: &Vector, samples: &(f32, f32)) -> (Colorf, Vector, f32) {
        let mut w_h = self.microfacet.sample(w_o, samples);
        if !bxdf::same_hemisphere(w_o, &w_h) {
            w_h = -w_h;
        }
        let eta = self.eta_for_interaction(w_o);
        if let Some(w_i) = linalg::refract(w_o, &w_h, eta.0, eta.1) {
            if bxdf::same_hemisphere(w_o, &w_i) {
                (Colorf::black(), Vector::broadcast(0.0), 0.0)
            } else {
                let pdf = self.microfacet.pdf(&w_h)
                    * MicrofacetTransmission::jacobian(w_o, &w_i, &w_h, eta);
                (self.eval(w_o, &w_i), w_i, pdf)
            }
        } else {
            (Colorf::black(), Vector::broadcast(0.0), 0.0)
        }
    }
    fn pdf(&self, w_o: &Vector, w_i: &Vector) -> f32 {
        if bxdf::same_hemisphere(w_o, w_i) {
            0.0
        } else {
            let eta = self.eta_for_interaction(w_o);
            if let Some(w_h) = MicrofacetTransmission::half_vector(w_o, w_i, eta) {
                self.microfacet.pdf(&w_h) * MicrofacetTransmission::jacobian(w_o, w_i, &w_h, eta)
            } else {
                0.0
            }
        }
    }
}

<commit_msg>On rare occasions I can get the Jacobian denom = 0 and get inf color??<commit_after>//! This module provides a microfacet model for transmission (a BTDF), see
//! [Walter et al. 07](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)
//! for details.

use std::f32;
use enum_set::EnumSet;

use linalg::{self, Vector};
use film::Colorf;
use bxdf::{self, BxDF, BxDFType};
use bxdf::fresnel::{Dielectric, Fresnel};
use bxdf::microfacet::{MicrofacetDistribution};

/// Struct providing the microfacet BTDF, implemented as described in
/// [Walter et al. 07](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)
pub struct MicrofacetTransmission {
    reflectance: Colorf,
    fresnel: Dielectric,
    /// Microfacet distribution describing the structure of the microfacets of
    /// the material
    microfacet: Box<MicrofacetDistribution + Send + Sync>,
}

impl MicrofacetTransmission {
    /// Create a new transmissive microfacet BRDF
    pub fn new(c: &Colorf, fresnel: Dielectric,
               microfacet: Box<MicrofacetDistribution + Send + Sync>) -> MicrofacetTransmission {
        MicrofacetTransmission { reflectance: *c, fresnel: fresnel, microfacet: microfacet }
    }
    /// Convenience method for getting `eta_i` and `eta_t` in the right order for if
    /// we're entering or exiting this material based on the direction of the outgoing
    /// ray.
    fn eta_for_interaction(&self, w_o: &Vector) -> (f32, f32) {
        if bxdf::cos_theta(w_o) > 0.0 {
            (self.fresnel.eta_i, self.fresnel.eta_t)
        } else {
            (self.fresnel.eta_t, self.fresnel.eta_i)
        }
    }
    /// Compute the Jacobian for the change of variables (see [Walter et al 07] section 4.2),
    /// here we compute equation 17 in that section.
    fn jacobian(w_o: &Vector, w_i: &Vector, w_h: &Vector, eta: (f32, f32)) -> f32 {
        let wi_dot_h = linalg::dot(w_i, w_h);
        let wo_dot_h = linalg::dot(w_o, w_h);
        let denom = f32::powf(eta.0 * wi_dot_h + eta.1 * wo_dot_h, 2.0);
        if denom == 0.0 {
            0.0
        } else {
            f32::powf(eta.1, 2.0) * f32::abs(wo_dot_h) / denom
        }
    }
    fn half_vector(w_o: &Vector, w_i: &Vector, eta: (f32, f32)) -> Option<Vector> {
        let w_h = -eta.0 * *w_o - eta.1 * *w_i;
        if w_h.x == 0.0 && w_h.y == 0.0 && w_h.z == 0.0 {
            None
        } else {
            Some(w_h.normalized())
        }
    }
}

impl BxDF for MicrofacetTransmission {
    fn bxdf_type(&self) -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Glossy);
        e.insert(BxDFType::Transmission);
        e
    }
    fn eval(&self, w_o: &Vector, w_i: &Vector) -> Colorf {
        if bxdf::same_hemisphere(w_o, w_i) {
            return Colorf::black();
        }
        let cos_to = bxdf::cos_theta(w_o);
        let cos_ti = bxdf::cos_theta(w_i);
        if cos_to == 0.0 || cos_ti == 0.0 {
            return Colorf::black();
        }
        let eta = self.eta_for_interaction(w_o);
        if let Some(w_h) = MicrofacetTransmission::half_vector(w_o, w_i, eta) {
            let d = self.microfacet.normal_distribution(&w_h);
            let f = Colorf::broadcast(1.0) - self.fresnel.fresnel(linalg::dot(w_o, &w_h));
            let g = self.microfacet.shadowing_masking(w_i, w_o, &w_h);
            let wi_dot_h = linalg::dot(w_i, &w_h);
            let jacobian = MicrofacetTransmission::jacobian(w_o, w_i, &w_h, eta);
            self.reflectance * (f32::abs(wi_dot_h) / (f32::abs(w_i.z) * f32::abs(w_o.z)))
                * (f * g * d) * jacobian
        } else {
            Colorf::black()
        }
    }
    fn sample(&self, w_o: &Vector, samples: &(f32, f32)) -> (Colorf, Vector, f32) {
        let mut w_h = self.microfacet.sample(w_o, samples);
        if !bxdf::same_hemisphere(w_o, &w_h) {
            w_h = -w_h;
        }
        let eta = self.eta_for_interaction(w_o);
        if let Some(w_i) = linalg::refract(w_o, &w_h, eta.0, eta.1) {
            if bxdf::same_hemisphere(w_o, &w_i) {
                (Colorf::black(), Vector::broadcast(0.0), 0.0)
            } else {
                let pdf = self.microfacet.pdf(&w_h)
                    * MicrofacetTransmission::jacobian(w_o, &w_i, &w_h, eta);
                (self.eval(w_o, &w_i), w_i, pdf)
            }
        } else {
            (Colorf::black(), Vector::broadcast(0.0), 0.0)
        }
    }
    fn pdf(&self, w_o: &Vector, w_i: &Vector) -> f32 {
        if bxdf::same_hemisphere(w_o, w_i) {
            0.0
        } else {
            let eta = self.eta_for_interaction(w_o);
            if let Some(w_h) = MicrofacetTransmission::half_vector(w_o, w_i, eta) {
                self.microfacet.pdf(&w_h) * MicrofacetTransmission::jacobian(w_o, w_i, &w_h, eta)
            } else {
                0.0
            }
        }
    }
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::Path;
use std::str;

use serde_json;
use semver::Version;

use core::dependency::Dependency;
use core::{PackageId, SourceId, Summary};
use sources::registry::{RegistryPackage, INDEX_LOCK};
use sources::registry::RegistryData;
use util::{internal, CargoResult, Config, Filesystem};

pub struct RegistryIndex<'cfg> {
    source_id: SourceId,
    path: Filesystem,
    cache: HashMap<String, Vec<(Summary, bool)>>,
    hashes: HashMap<String, HashMap<Version, String>>, // (name, vers) => cksum
    config: &'cfg Config,
    locked: bool,
}

impl<'cfg> RegistryIndex<'cfg> {
    pub fn new(
        id: &SourceId,
        path: &Filesystem,
        config: &'cfg Config,
        locked: bool,
    ) -> RegistryIndex<'cfg> {
        RegistryIndex {
            source_id: id.clone(),
            path: path.clone(),
            cache: HashMap::new(),
            hashes: HashMap::new(),
            config,
            locked,
        }
    }

    /// Return the hash listed for a specified PackageId.
    pub fn hash(&mut self, pkg: &PackageId, load: &mut RegistryData) -> CargoResult<String> {
        let name = &*pkg.name();
        let version = pkg.version();
        if let Some(s) = self.hashes.get(name).and_then(|v| v.get(version)) {
            return Ok(s.clone());
        }
        // Ok, we're missing the key, so parse the index file to load it.
        self.summaries(name, load)?;
        self.hashes
            .get(name)
            .and_then(|v| v.get(version))
            .ok_or_else(|| internal(format!("no hash listed for {}", pkg)))
            .map(|s| s.clone())
    }

    /// Parse the on-disk metadata for the package provided
    ///
    /// Returns a list of pairs of (summary, yanked) for the package name
    /// specified.
    pub fn summaries(
        &mut self,
        name: &str,
        load: &mut RegistryData,
    ) -> CargoResult<&Vec<(Summary, bool)>> {
        if self.cache.contains_key(name) {
            return Ok(&self.cache[name]);
        }
        let summaries = self.load_summaries(name, load)?;
        self.cache.insert(name.to_string(), summaries);
        Ok(&self.cache[name])
    }

    fn load_summaries(
        &mut self,
        name: &str,
        load: &mut RegistryData,
    ) -> CargoResult<Vec<(Summary, bool)>> {
        let (root, _lock) = if self.locked {
            let lock = self.path
                .open_ro(Path::new(INDEX_LOCK), self.config, "the registry index");
            match lock {
                Ok(lock) => (lock.path().parent().unwrap().to_path_buf(), Some(lock)),
                Err(_) => return Ok(Vec::new()),
            }
        } else {
            (self.path.clone().into_path_unlocked(), None)
        };

        let fs_name = name.chars()
            .flat_map(|c| c.to_lowercase())
            .collect::<String>();

        // see module comment for why this is structured the way it is
        let path = match fs_name.len() {
            1 => format!("1/{}", fs_name),
            2 => format!("2/{}", fs_name),
            3 => format!("3/{}/{}", &fs_name[..1], fs_name),
            _ => format!("{}/{}/{}", &fs_name[0..2], &fs_name[2..4], fs_name),
        };
        let mut ret = Vec::new();
        let mut hit_closure = false;
        let err = load.load(&root, Path::new(&path), &mut |contents| {
            hit_closure = true;
            let contents = str::from_utf8(contents)
                .map_err(|_| format_err!("registry index file was not valid utf-8"))?;
            ret.reserve(contents.lines().count());
            let lines = contents.lines().map(|s| s.trim()).filter(|l| !l.is_empty());

            let online = !self.config.cli_unstable().offline;
            // Attempt forwards-compatibility on the index by ignoring
            // everything that we ourselves don't understand, that should
            // allow future cargo implementations to break the
            // interpretation of each line here and older cargo will simply
            // ignore the new lines.
            ret.extend(lines.filter_map(|line| {
                self.parse_registry_package(line).ok().and_then(|v| {
                    if online || load.is_crate_downloaded(v.0.package_id()) {
                        Some(v)
                    } else {
                        None
                    }
                })
            }));

            Ok(())
        });

        // We ignore lookup failures as those are just crates which don't exist
        // or we haven't updated the registry yet. If we actually ran the
        // closure though then we care about those errors.
        if hit_closure {
            err?;
        }

        Ok(ret)
    }

    /// Parse a line from the registry's index file into a Summary for a
    /// package.
    ///
    /// The returned boolean is whether or not the summary has been yanked.
    fn parse_registry_package(&mut self, line: &str) -> CargoResult<(Summary, bool)> {
        let RegistryPackage {
            name,
            vers,
            cksum,
            deps,
            features,
            yanked,
            links,
        } = super::DEFAULT_ID.set(&self.source_id, || {
            serde_json::from_str::<RegistryPackage>(line)
        })?;
        let pkgid = PackageId::new(&name, &vers, &self.source_id)?;
        let summary = Summary::new(pkgid, deps.inner, features, links)?;
        let summary = summary.set_checksum(cksum.clone());
        if self.hashes.contains_key(&name[..]) {
            self.hashes.get_mut(&name[..]).unwrap().insert(vers, cksum);
        } else {
            self.hashes
                .entry(name.into_owned())
                .or_insert_with(HashMap::new)
                .insert(vers, cksum);
        }
        Ok((summary, yanked.unwrap_or(false)))
    }

    pub fn query(
        &mut self,
        dep: &Dependency,
        load: &mut RegistryData,
        f: &mut FnMut(Summary),
    ) -> CargoResult<()> {
        let source_id = self.source_id.clone();
        let summaries = self.summaries(&*dep.name(), load)?;
        let summaries = summaries
            .iter()
            .filter(|&&(_, yanked)| dep.source_id().precise().is_some() || !yanked)
            .map(|s| s.0.clone());

        // Handle `cargo update --precise` here. If specified, our own source
        // will have a precise version listed of the form
        // `<pkg>=<p_req>o-><f_req>` where `<pkg>` is the name of a crate on
        // this source, `<p_req>` is the version installed and `<f_req> is the
        // version requested (argument to `--precise`).
        let summaries = summaries.filter(|s| match source_id.precise() {
            Some(p) if p.starts_with(&*dep.name()) && p[dep.name().len()..].starts_with('=') => {
                let vers: Vec<&str> = p[dep.name().len() + 1..].split("->").collect();
                    if dep.version_req().matches(&Version::parse(vers[0]).unwrap()) {
                        return vers[1] == s.version().to_string()
                    }

                    true
            }
            _ => true,
        });

        for summary in summaries {
            if dep.matches(&summary) {
                f(summary);
            }
        }
        Ok(())
    }
}
<commit_msg>cargo fmt<commit_after>use std::collections::HashMap;
use std::path::Path;
use std::str;

use serde_json;
use semver::Version;

use core::dependency::Dependency;
use core::{PackageId, SourceId, Summary};
use sources::registry::{RegistryPackage, INDEX_LOCK};
use sources::registry::RegistryData;
use util::{internal, CargoResult, Config, Filesystem};

pub struct RegistryIndex<'cfg> {
    source_id: SourceId,
    path: Filesystem,
    cache: HashMap<String, Vec<(Summary, bool)>>,
    hashes: HashMap<String, HashMap<Version, String>>, // (name, vers) => cksum
    config: &'cfg Config,
    locked: bool,
}

impl<'cfg> RegistryIndex<'cfg> {
    pub fn new(
        id: &SourceId,
        path: &Filesystem,
        config: &'cfg Config,
        locked: bool,
    ) -> RegistryIndex<'cfg> {
        RegistryIndex {
            source_id: id.clone(),
            path: path.clone(),
            cache: HashMap::new(),
            hashes: HashMap::new(),
            config,
            locked,
        }
    }

    /// Return the hash listed for a specified PackageId.
    pub fn hash(&mut self, pkg: &PackageId, load: &mut RegistryData) -> CargoResult<String> {
        let name = &*pkg.name();
        let version = pkg.version();
        if let Some(s) = self.hashes.get(name).and_then(|v| v.get(version)) {
            return Ok(s.clone());
        }
        // Ok, we're missing the key, so parse the index file to load it.
        self.summaries(name, load)?;
        self.hashes
            .get(name)
            .and_then(|v| v.get(version))
            .ok_or_else(|| internal(format!("no hash listed for {}", pkg)))
            .map(|s| s.clone())
    }

    /// Parse the on-disk metadata for the package provided
    ///
    /// Returns a list of pairs of (summary, yanked) for the package name
    /// specified.
    pub fn summaries(
        &mut self,
        name: &str,
        load: &mut RegistryData,
    ) -> CargoResult<&Vec<(Summary, bool)>> {
        if self.cache.contains_key(name) {
            return Ok(&self.cache[name]);
        }
        let summaries = self.load_summaries(name, load)?;
        self.cache.insert(name.to_string(), summaries);
        Ok(&self.cache[name])
    }

    fn load_summaries(
        &mut self,
        name: &str,
        load: &mut RegistryData,
    ) -> CargoResult<Vec<(Summary, bool)>> {
        let (root, _lock) = if self.locked {
            let lock = self.path
                .open_ro(Path::new(INDEX_LOCK), self.config, "the registry index");
            match lock {
                Ok(lock) => (lock.path().parent().unwrap().to_path_buf(), Some(lock)),
                Err(_) => return Ok(Vec::new()),
            }
        } else {
            (self.path.clone().into_path_unlocked(), None)
        };

        let fs_name = name.chars()
            .flat_map(|c| c.to_lowercase())
            .collect::<String>();

        // see module comment for why this is structured the way it is
        let path = match fs_name.len() {
            1 => format!("1/{}", fs_name),
            2 => format!("2/{}", fs_name),
            3 => format!("3/{}/{}", &fs_name[..1], fs_name),
            _ => format!("{}/{}/{}", &fs_name[0..2], &fs_name[2..4], fs_name),
        };
        let mut ret = Vec::new();
        let mut hit_closure = false;
        let err = load.load(&root, Path::new(&path), &mut |contents| {
            hit_closure = true;
            let contents = str::from_utf8(contents)
                .map_err(|_| format_err!("registry index file was not valid utf-8"))?;
            ret.reserve(contents.lines().count());
            let lines = contents.lines().map(|s| s.trim()).filter(|l| !l.is_empty());

            let online = !self.config.cli_unstable().offline;
            // Attempt forwards-compatibility on the index by ignoring
            // everything that we ourselves don't understand, that should
            // allow future cargo implementations to break the
            // interpretation of each line here and older cargo will simply
            // ignore the new lines.
            ret.extend(lines.filter_map(|line| {
                self.parse_registry_package(line).ok().and_then(|v| {
                    if online || load.is_crate_downloaded(v.0.package_id()) {
                        Some(v)
                    } else {
                        None
                    }
                })
            }));

            Ok(())
        });

        // We ignore lookup failures as those are just crates which don't exist
        // or we haven't updated the registry yet. If we actually ran the
        // closure though then we care about those errors.
        if hit_closure {
            err?;
        }

        Ok(ret)
    }

    /// Parse a line from the registry's index file into a Summary for a
    /// package.
    ///
    /// The returned boolean is whether or not the summary has been yanked.
    fn parse_registry_package(&mut self, line: &str) -> CargoResult<(Summary, bool)> {
        let RegistryPackage {
            name,
            vers,
            cksum,
            deps,
            features,
            yanked,
            links,
        } = super::DEFAULT_ID.set(&self.source_id, || {
            serde_json::from_str::<RegistryPackage>(line)
        })?;
        let pkgid = PackageId::new(&name, &vers, &self.source_id)?;
        let summary = Summary::new(pkgid, deps.inner, features, links)?;
        let summary = summary.set_checksum(cksum.clone());
        if self.hashes.contains_key(&name[..]) {
            self.hashes.get_mut(&name[..]).unwrap().insert(vers, cksum);
        } else {
            self.hashes
                .entry(name.into_owned())
                .or_insert_with(HashMap::new)
                .insert(vers, cksum);
        }
        Ok((summary, yanked.unwrap_or(false)))
    }

    pub fn query(
        &mut self,
        dep: &Dependency,
        load: &mut RegistryData,
        f: &mut FnMut(Summary),
    ) -> CargoResult<()> {
        let source_id = self.source_id.clone();
        let summaries = self.summaries(&*dep.name(), load)?;
        let summaries = summaries
            .iter()
            .filter(|&&(_, yanked)| dep.source_id().precise().is_some() || !yanked)
            .map(|s| s.0.clone());

        // Handle `cargo update --precise` here. If specified, our own source
        // will have a precise version listed of the form
        // `<pkg>=<p_req>o-><f_req>` where `<pkg>` is the name of a crate on
        // this source, `<p_req>` is the version installed and `<f_req> is the
        // version requested (argument to `--precise`).
        let summaries = summaries.filter(|s| match source_id.precise() {
            Some(p) if p.starts_with(&*dep.name()) && p[dep.name().len()..].starts_with('=') => {
                let vers: Vec<&str> = p[dep.name().len() + 1..].split("->").collect();
                if dep.version_req().matches(&Version::parse(vers[0]).unwrap()) {
                    return vers[1] == s.version().to_string()
                } {
                    true
                }
            }
            _ => true,
        });

        for summary in summaries {
            if dep.matches(&summary) {
                f(summary);
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::{
    boxed::Box,
    future::Future,
    sync::Arc,
    time::Duration,
    pin::Pin,
    task::{Context as FutContext, Poll},
};
use tokio::{
    sync::mpsc::{
        unbounded_channel,
        UnboundedReceiver as Receiver,
        UnboundedSender as Sender,
    },
    time::{Delay, delay_for},
};
use futures::{
    future::BoxFuture,
    stream::{Stream, StreamExt},
};
use crate::{
    client::bridge::gateway::ShardMessenger,
    model::channel::Reaction,
    model::id::UserId,
};

macro_rules! impl_reaction_collector {
    ($($name:ident;)*) => {
        $(
            impl<'a> $name<'a> {
                /// Limits how many messages will attempt to be filtered.
                ///
                /// The filter checks whether the message has been sent
                /// in the right guild, channel, and by the right author.
                pub fn filter_limit(mut self, limit: u32) -> Self {
                    self.filter.as_mut().unwrap().filter_limit = Some(limit);

                    self
                }

                /// Limits how many reactions can be collected.
                ///
                /// A reaction is considered *collected*, if the reaction
                /// passes all the requirements.
                pub fn collect_limit(mut self, limit: u32) -> Self {
                    self.filter.as_mut().unwrap().collect_limit = Some(limit);

                    self
                }

                /// Sets a filter function where reactions passed to the function must
                /// return `true`, otherwise the reaction won't be collected.
                /// This is the last instance to pass for a reaction to count as *collected*.
                ///
                /// This function is intended to be a reaction content filter.
                pub fn filter<F: Fn(&Arc<Reaction>) -> bool + 'static + Send + Sync>(mut self, function: F) -> Self {
                    self.filter.as_mut().unwrap().filter = Some(Arc::new(function));

                    self
                }

                /// Sets the required author ID of a reaction.
                /// If a reaction is not issued by a user with this ID, it won't be received.
                pub fn author_id(mut self, author_id: impl Into<u64>) -> Self {
                    self.filter.as_mut().unwrap().author_id = Some(author_id.into());

                    self
                }

                /// Sets the message on which the reaction must occur.
                /// If a reaction is not on a message with this ID, it won't be received.
                pub fn message_id(mut self, message_id: impl Into<u64>) -> Self {
                    self.filter.as_mut().unwrap().message_id = Some(message_id.into());

                    self
                }

                /// Sets the guild in which the reaction must occur.
                /// If a reaction is not on a message with this ID, it won't be received.
                pub fn guild_id(mut self, guild_id: impl Into<u64>) -> Self {
                    self.filter.as_mut().unwrap().guild_id = Some(guild_id.into());

                    self
                }

                /// Sets the channel on which the reaction must occur.
                /// If a reaction is not on a message with this ID, it won't be received.
                pub fn channel_id(mut self, channel_id: impl Into<u64>) -> Self {
                    self.filter.as_mut().unwrap().channel_id = Some(channel_id.into());

                    self
                }

                /// If set to `true`, added reactions will be collected.
                ///
                /// Set to `true` by default.
                pub fn added(mut self, is_accepted: bool) -> Self {
                    self.filter.as_mut().unwrap().accept_added = is_accepted;

                    self
                }

                /// If set to `true`, removed reactions will be collected.
                ///
                /// Set to `false` by default.
                pub fn removed(mut self, is_accepted: bool) -> Self {
                    self.filter.as_mut().unwrap().accept_removed = is_accepted;

                    self
                }

                /// Sets a `duration` for how long the collector shall receive
                /// reactions.
                pub fn timeout(mut self, duration: Duration) -> Self {
                    self.timeout = Some(delay_for(duration));

                    self
                }
            }
        )*
    }
}

/// Marks whether the reaction has been added or removed.
#[derive(Debug)]
pub enum ReactionAction {
    Added(Arc<Reaction>),
    Removed(Arc<Reaction>),
}

impl ReactionAction {
    pub fn as_inner_ref(&self) -> &Arc<Reaction> {
        match self {
            Self::Added(inner) => inner,
            Self::Removed(inner) => inner,
        }
    }

    pub fn is_added(&self) -> bool {
        if let Self::Added(_) = &self {
            true
        } else {
            false
        }
    }

    pub fn is_removed(&self) -> bool {
        if let Self::Removed(_) = &self {
            true
        } else {
            false
        }
    }
}

/// Filters events on the shard's end and sends them to the collector.
#[derive(Clone, Debug)]
pub struct ReactionFilter {
    filtered: u32,
    collected: u32,
    options: FilterOptions,
    sender: Sender<Arc<ReactionAction>>,
}

impl ReactionFilter {
    /// Creates a new filter
    fn new(options: FilterOptions) -> (Self, Receiver<Arc<ReactionAction>>) {
        let (sender, receiver) = unbounded_channel();

        let filter = Self {
            filtered: 0,
            collected: 0,
            sender,
            options,
        };

        (filter, receiver)
    }

    /// Sends a `reaction` to the consuming collector if the `reaction` conforms
    /// to the constraints and the limits are not reached yet.
    pub(crate) fn send_reaction(&mut self, reaction: &Arc<ReactionAction>) -> bool {
        if self.is_passing_constraints(&reaction) {
            self.collected += 1;

            if self.sender.send(Arc::clone(reaction)).is_err() {
                return false;
            }
        }

        self.filtered += 1;

        self.is_within_limits()
    }

    /// Checks if the `reaction` passes set constraints.
    /// Constraints are optional, as it is possible to limit reactions to
    /// be sent by a specific author or in a specifc guild.
    fn is_passing_constraints(&self, reaction: &Arc<ReactionAction>) -> bool {
        let reaction = match **reaction {
            ReactionAction::Added(ref reaction) => if self.options.accept_added {
                reaction
            } else {
                return false;
            },
            ReactionAction::Removed(ref reaction) => if self.options.accept_removed {
                reaction
            } else {
                return false;
            },
        };

        self.options.guild_id.map_or(true, |id| { Some(id) == reaction.guild_id.map(|g| g.0) })
        && self.options.message_id.map_or(true, |id| { id == reaction.message_id.0 })
        && self.options.channel_id.map_or(true, |id| { id == reaction.channel_id.0 })
        && self.options.author_id.map_or(true, |id| { id == reaction.user_id.unwrap_or(UserId(0)).0 })
        && self.options.filter.as_ref().map_or(true, |f| f(&reaction))
    }

    /// Checks if the filter is within set receive and collect limits.
    /// A reaction is considered *received* even when it does not meet the
    /// constraints.
    fn is_within_limits(&self) -> bool {
        self.options.filter_limit.map_or(true, |limit| { self.filtered < limit })
        && self.options.collect_limit.map_or(true, |limit| { self.collected < limit })
    }
}

#[derive(Clone)]
struct FilterOptions {
    filter_limit: Option<u32>,
    collect_limit: Option<u32>,
    filter: Option<Arc<dyn Fn(&Arc<Reaction>) -> bool + 'static + Send + Sync>>,
    channel_id: Option<u64>,
    guild_id: Option<u64>,
    author_id: Option<u64>,
    message_id: Option<u64>,
    accept_added: bool,
    accept_removed: bool,
}

impl Default for FilterOptions {
    fn default() -> Self {
        Self {
            filter_limit: None,
            collect_limit: None,
            filter: None,
            channel_id: None,
            guild_id: None,
            author_id: None,
            message_id: None,
            accept_added: true,
            accept_removed: false,
        }
    }
}

// Implement the common setters for all reaction collector types.
// This avoids using a trait that the user would need to import in
// order to use any of these methods.
impl_reaction_collector! {
    CollectReaction;
    ReactionCollectorBuilder;
}

pub struct ReactionCollectorBuilder<'a> {
    filter: Option<FilterOptions>,
    shard: Option<ShardMessenger>,
    timeout: Option<Delay>,
    fut: Option<BoxFuture<'a, ReactionCollector>>,
}

impl<'a> ReactionCollectorBuilder<'a> {
    pub fn new(shard_messenger: impl AsRef<ShardMessenger>) -> Self {
        Self {
            filter: Some(FilterOptions::default()),
            shard: Some(shard_messenger.as_ref().clone()),
            timeout: None,
            fut: None,
        }
    }
}

impl<'a> Future for ReactionCollectorBuilder<'a> {
    type Output = ReactionCollector;

    fn poll(mut self: Pin<&mut Self>, ctx: &mut FutContext<'_>) -> Poll<Self::Output> {
        if self.fut.is_none() {
            let shard_messenger = self.shard.take().unwrap();
            let (filter, receiver) = ReactionFilter::new(self.filter.take().unwrap());
            let timeout = self.timeout.take();

            self.fut = Some(Box::pin(async move {
                shard_messenger.set_reaction_filter(filter);

                ReactionCollector {
                    receiver: Box::pin(receiver),
                    timeout: timeout.map(Box::pin),
                }
            }))
        }

        self.fut.as_mut().unwrap().as_mut().poll(ctx)
    }
}

pub struct CollectReaction<'a> {
    filter: Option<FilterOptions>,
    shard: Option<ShardMessenger>,
    timeout: Option<Delay>,
    fut: Option<BoxFuture<'a, Option<Arc<ReactionAction>>>>,
}

impl<'a> CollectReaction<'a> {
    pub fn new(shard_messenger: impl AsRef<ShardMessenger>) -> Self {
        Self {
            filter: Some(FilterOptions::default()),
            shard: Some(shard_messenger.as_ref().clone()),
            timeout: None,
            fut: None,
        }
    }
}

impl<'a> Future for CollectReaction<'a> {
    type Output = Option<Arc<ReactionAction>>;

    fn poll(mut self: Pin<&mut Self>, ctx: &mut FutContext<'_>) -> Poll<Self::Output> {
        if self.fut.is_none() {
            let shard_messenger = self.shard.take().unwrap();
            let (filter, receiver) = ReactionFilter::new(self.filter.take().unwrap());
            let timeout = self.timeout.take();

            self.fut = Some(Box::pin(async move {
                shard_messenger.set_reaction_filter(filter);

                ReactionCollector {
                    receiver: Box::pin(receiver),
                    timeout: timeout.map(Box::pin),
                }.next().await
            }))
        }

        self.fut.as_mut().unwrap().as_mut().poll(ctx)
    }
}

impl std::fmt::Debug for FilterOptions {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ReactionFilter")
            .field("collect_limit", &self.collect_limit)
            .field("filter", &"Option<Arc<dyn Fn(&Arc<Reaction>) -> bool + 'static + Send + Sync>>")
            .field("channel_id", &self.channel_id)
            .field("guild_id", &self.guild_id)
            .field("author_id", &self.author_id)
            .finish()
    }
}

/// A reaction collector receives reactions matching a the given filter for a
/// set duration.
pub struct ReactionCollector {
    receiver: Pin<Box<Receiver<Arc<ReactionAction>>>>,
    timeout: Option<Pin<Box<Delay>>>,
}

impl ReactionCollector {
    /// Stops collecting, this will implicitly be done once the
    /// collector drops.
    /// In case the drop does not appear until later, it is preferred to
    /// stop the collector early.
    pub fn stop(mut self) {
        self.receiver.close();
    }
}

impl Stream for ReactionCollector {
    type Item = Arc<ReactionAction>;
    fn poll_next(mut self: Pin<&mut Self>, ctx: &mut FutContext<'_>) -> Poll<Option<Self::Item>> {
        if let Some(ref mut timeout) = self.timeout {

            match timeout.as_mut().poll(ctx) {
                Poll::Ready(_) => {
                    return Poll::Ready(None);
                },
                Poll::Pending => (),
            }
        }

        self.receiver.as_mut().poll_next(ctx)
    }
}

impl Drop for ReactionCollector {
    fn drop(&mut self) {
        self.receiver.close();
    }
}
<commit_msg>Fix doc comments for `ReactionCollector`<commit_after>use std::{
    boxed::Box,
    future::Future,
    sync::Arc,
    time::Duration,
    pin::Pin,
    task::{Context as FutContext, Poll},
};
use tokio::{
    sync::mpsc::{
        unbounded_channel,
        UnboundedReceiver as Receiver,
        UnboundedSender as Sender,
    },
    time::{Delay, delay_for},
};
use futures::{
    future::BoxFuture,
    stream::{Stream, StreamExt},
};
use crate::{
    client::bridge::gateway::ShardMessenger,
    model::channel::Reaction,
    model::id::UserId,
};

macro_rules! impl_reaction_collector {
    ($($name:ident;)*) => {
        $(
            impl<'a> $name<'a> {
                /// Limits how many messages will attempt to be filtered.
                ///
                /// The filter checks whether the message has been sent
                /// in the right guild, channel, and by the right author.
                pub fn filter_limit(mut self, limit: u32) -> Self {
                    self.filter.as_mut().unwrap().filter_limit = Some(limit);

                    self
                }

                /// Limits how many reactions can be collected.
                ///
                /// A reaction is considered *collected*, if the reaction
                /// passes all the requirements.
                pub fn collect_limit(mut self, limit: u32) -> Self {
                    self.filter.as_mut().unwrap().collect_limit = Some(limit);

                    self
                }

                /// Sets a filter function where reactions passed to the function must
                /// return `true`, otherwise the reaction won't be collected.
                /// This is the last instance to pass for a reaction to count as *collected*.
                ///
                /// This function is intended to be a reaction content filter.
                pub fn filter<F: Fn(&Arc<Reaction>) -> bool + 'static + Send + Sync>(mut self, function: F) -> Self {
                    self.filter.as_mut().unwrap().filter = Some(Arc::new(function));

                    self
                }

                /// Sets the required author ID of a reaction.
                /// If a reaction is not issued by a user with this ID, it won't be received.
                pub fn author_id(mut self, author_id: impl Into<u64>) -> Self {
                    self.filter.as_mut().unwrap().author_id = Some(author_id.into());

                    self
                }

                /// Sets the message on which the reaction must occur.
                /// If a reaction is not on a message with this ID, it won't be received.
                pub fn message_id(mut self, message_id: impl Into<u64>) -> Self {
                    self.filter.as_mut().unwrap().message_id = Some(message_id.into());

                    self
                }

                /// Sets the guild in which the reaction must occur.
                /// If a reaction is not on a message with this guild ID, it won't be received.
                pub fn guild_id(mut self, guild_id: impl Into<u64>) -> Self {
                    self.filter.as_mut().unwrap().guild_id = Some(guild_id.into());

                    self
                }

                /// Sets the channel on which the reaction must occur.
                /// If a reaction is not on a message with this channel ID, it won't be received.
                pub fn channel_id(mut self, channel_id: impl Into<u64>) -> Self {
                    self.filter.as_mut().unwrap().channel_id = Some(channel_id.into());

                    self
                }

                /// If set to `true`, added reactions will be collected.
                ///
                /// Set to `true` by default.
                pub fn added(mut self, is_accepted: bool) -> Self {
                    self.filter.as_mut().unwrap().accept_added = is_accepted;

                    self
                }

                /// If set to `true`, removed reactions will be collected.
                ///
                /// Set to `false` by default.
                pub fn removed(mut self, is_accepted: bool) -> Self {
                    self.filter.as_mut().unwrap().accept_removed = is_accepted;

                    self
                }

                /// Sets a `duration` for how long the collector shall receive
                /// reactions.
                pub fn timeout(mut self, duration: Duration) -> Self {
                    self.timeout = Some(delay_for(duration));

                    self
                }
            }
        )*
    }
}

/// Marks whether the reaction has been added or removed.
#[derive(Debug)]
pub enum ReactionAction {
    Added(Arc<Reaction>),
    Removed(Arc<Reaction>),
}

impl ReactionAction {
    pub fn as_inner_ref(&self) -> &Arc<Reaction> {
        match self {
            Self::Added(inner) => inner,
            Self::Removed(inner) => inner,
        }
    }

    pub fn is_added(&self) -> bool {
        if let Self::Added(_) = &self {
            true
        } else {
            false
        }
    }

    pub fn is_removed(&self) -> bool {
        if let Self::Removed(_) = &self {
            true
        } else {
            false
        }
    }
}

/// Filters events on the shard's end and sends them to the collector.
#[derive(Clone, Debug)]
pub struct ReactionFilter {
    filtered: u32,
    collected: u32,
    options: FilterOptions,
    sender: Sender<Arc<ReactionAction>>,
}

impl ReactionFilter {
    /// Creates a new filter
    fn new(options: FilterOptions) -> (Self, Receiver<Arc<ReactionAction>>) {
        let (sender, receiver) = unbounded_channel();

        let filter = Self {
            filtered: 0,
            collected: 0,
            sender,
            options,
        };

        (filter, receiver)
    }

    /// Sends a `reaction` to the consuming collector if the `reaction` conforms
    /// to the constraints and the limits are not reached yet.
    pub(crate) fn send_reaction(&mut self, reaction: &Arc<ReactionAction>) -> bool {
        if self.is_passing_constraints(&reaction) {
            self.collected += 1;

            if self.sender.send(Arc::clone(reaction)).is_err() {
                return false;
            }
        }

        self.filtered += 1;

        self.is_within_limits()
    }

    /// Checks if the `reaction` passes set constraints.
    /// Constraints are optional, as it is possible to limit reactions to
    /// be sent by a specific author or in a specifc guild.
    fn is_passing_constraints(&self, reaction: &Arc<ReactionAction>) -> bool {
        let reaction = match **reaction {
            ReactionAction::Added(ref reaction) => if self.options.accept_added {
                reaction
            } else {
                return false;
            },
            ReactionAction::Removed(ref reaction) => if self.options.accept_removed {
                reaction
            } else {
                return false;
            },
        };

        self.options.guild_id.map_or(true, |id| { Some(id) == reaction.guild_id.map(|g| g.0) })
        && self.options.message_id.map_or(true, |id| { id == reaction.message_id.0 })
        && self.options.channel_id.map_or(true, |id| { id == reaction.channel_id.0 })
        && self.options.author_id.map_or(true, |id| { id == reaction.user_id.unwrap_or(UserId(0)).0 })
        && self.options.filter.as_ref().map_or(true, |f| f(&reaction))
    }

    /// Checks if the filter is within set receive and collect limits.
    /// A reaction is considered *received* even when it does not meet the
    /// constraints.
    fn is_within_limits(&self) -> bool {
        self.options.filter_limit.map_or(true, |limit| { self.filtered < limit })
        && self.options.collect_limit.map_or(true, |limit| { self.collected < limit })
    }
}

#[derive(Clone)]
struct FilterOptions {
    filter_limit: Option<u32>,
    collect_limit: Option<u32>,
    filter: Option<Arc<dyn Fn(&Arc<Reaction>) -> bool + 'static + Send + Sync>>,
    channel_id: Option<u64>,
    guild_id: Option<u64>,
    author_id: Option<u64>,
    message_id: Option<u64>,
    accept_added: bool,
    accept_removed: bool,
}

impl Default for FilterOptions {
    fn default() -> Self {
        Self {
            filter_limit: None,
            collect_limit: None,
            filter: None,
            channel_id: None,
            guild_id: None,
            author_id: None,
            message_id: None,
            accept_added: true,
            accept_removed: false,
        }
    }
}

// Implement the common setters for all reaction collector types.
// This avoids using a trait that the user would need to import in
// order to use any of these methods.
impl_reaction_collector! {
    CollectReaction;
    ReactionCollectorBuilder;
}

pub struct ReactionCollectorBuilder<'a> {
    filter: Option<FilterOptions>,
    shard: Option<ShardMessenger>,
    timeout: Option<Delay>,
    fut: Option<BoxFuture<'a, ReactionCollector>>,
}

impl<'a> ReactionCollectorBuilder<'a> {
    pub fn new(shard_messenger: impl AsRef<ShardMessenger>) -> Self {
        Self {
            filter: Some(FilterOptions::default()),
            shard: Some(shard_messenger.as_ref().clone()),
            timeout: None,
            fut: None,
        }
    }
}

impl<'a> Future for ReactionCollectorBuilder<'a> {
    type Output = ReactionCollector;

    fn poll(mut self: Pin<&mut Self>, ctx: &mut FutContext<'_>) -> Poll<Self::Output> {
        if self.fut.is_none() {
            let shard_messenger = self.shard.take().unwrap();
            let (filter, receiver) = ReactionFilter::new(self.filter.take().unwrap());
            let timeout = self.timeout.take();

            self.fut = Some(Box::pin(async move {
                shard_messenger.set_reaction_filter(filter);

                ReactionCollector {
                    receiver: Box::pin(receiver),
                    timeout: timeout.map(Box::pin),
                }
            }))
        }

        self.fut.as_mut().unwrap().as_mut().poll(ctx)
    }
}

pub struct CollectReaction<'a> {
    filter: Option<FilterOptions>,
    shard: Option<ShardMessenger>,
    timeout: Option<Delay>,
    fut: Option<BoxFuture<'a, Option<Arc<ReactionAction>>>>,
}

impl<'a> CollectReaction<'a> {
    pub fn new(shard_messenger: impl AsRef<ShardMessenger>) -> Self {
        Self {
            filter: Some(FilterOptions::default()),
            shard: Some(shard_messenger.as_ref().clone()),
            timeout: None,
            fut: None,
        }
    }
}

impl<'a> Future for CollectReaction<'a> {
    type Output = Option<Arc<ReactionAction>>;

    fn poll(mut self: Pin<&mut Self>, ctx: &mut FutContext<'_>) -> Poll<Self::Output> {
        if self.fut.is_none() {
            let shard_messenger = self.shard.take().unwrap();
            let (filter, receiver) = ReactionFilter::new(self.filter.take().unwrap());
            let timeout = self.timeout.take();

            self.fut = Some(Box::pin(async move {
                shard_messenger.set_reaction_filter(filter);

                ReactionCollector {
                    receiver: Box::pin(receiver),
                    timeout: timeout.map(Box::pin),
                }.next().await
            }))
        }

        self.fut.as_mut().unwrap().as_mut().poll(ctx)
    }
}

impl std::fmt::Debug for FilterOptions {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ReactionFilter")
            .field("collect_limit", &self.collect_limit)
            .field("filter", &"Option<Arc<dyn Fn(&Arc<Reaction>) -> bool + 'static + Send + Sync>>")
            .field("channel_id", &self.channel_id)
            .field("guild_id", &self.guild_id)
            .field("author_id", &self.author_id)
            .finish()
    }
}

/// A reaction collector receives reactions matching a the given filter for a
/// set duration.
pub struct ReactionCollector {
    receiver: Pin<Box<Receiver<Arc<ReactionAction>>>>,
    timeout: Option<Pin<Box<Delay>>>,
}

impl ReactionCollector {
    /// Stops collecting, this will implicitly be done once the
    /// collector drops.
    /// In case the drop does not appear until later, it is preferred to
    /// stop the collector early.
    pub fn stop(mut self) {
        self.receiver.close();
    }
}

impl Stream for ReactionCollector {
    type Item = Arc<ReactionAction>;
    fn poll_next(mut self: Pin<&mut Self>, ctx: &mut FutContext<'_>) -> Poll<Option<Self::Item>> {
        if let Some(ref mut timeout) = self.timeout {

            match timeout.as_mut().poll(ctx) {
                Poll::Ready(_) => {
                    return Poll::Ready(None);
                },
                Poll::Pending => (),
            }
        }

        self.receiver.as_mut().poll_next(ctx)
    }
}

impl Drop for ReactionCollector {
    fn drop(&mut self) {
        self.receiver.close();
    }
}
<|endoftext|>


<commit_before>use std::env;

fn fibo(n: i32) -> i32 {
	if n < 2 {
		return n;
	}

	return fibo(n - 1) + fibo(n - 2);
}

fn main() {
	let args = env::args().collect::<Vec<String>>();
	let app_name = &args[0];
	if args.len() < 2 {
		println!("usage {:?} [number]", app_name);
	} else {
		let n = &args[1].parse::<i32>().unwrap();
		println!("{}", fibo(*n));
	}
}
<commit_msg>Added better error handling<commit_after>use std::env;

fn fibo(n: i32) -> i32 {
	if n < 2 {
		return n;
	}

	return fibo(n - 1) + fibo(n - 2);
}

fn main() {
	let args = env::args().collect::<Vec<String>>();
	let app_name = &args[0];
	if args.len() != 2 {
		println!("Error: Invalid number of arguments\nUsage: {:?} [number]", app_name);
		std::process::exit(1);
	} else {
		let n = args[1].parse::<i32>().unwrap_or_else(|e| {
			println!("Error parsing number '{}': {}", args[1], e);
			std::process::exit(1);
		});
		println!("{}", fibo(n));
	}
}
<|endoftext|>


<commit_before>use crate::spec::{Target, TargetOptions};

pub fn target() -> Target {
    let mut base = super::linux_musl_base::opts();
    base.max_atomic_width = Some(128);

    Target {
        llvm_target: "aarch64-unknown-linux-musl".to_string(),
        pointer_width: 64,
        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
        arch: "aarch64".to_string(),
        options: TargetOptions {
            features: "+outline-atomics".to_string(),
            mcount: "\u{1}_mcount".to_string(),
            ..base
        },
    }
}
<commit_msg>Rollup merge of #90044 - rusticstuff:disable_arm_outline_atomics_for_musl, r=workingjubilee<commit_after>use crate::spec::{Target, TargetOptions};

pub fn target() -> Target {
    let mut base = super::linux_musl_base::opts();
    base.max_atomic_width = Some(128);

    Target {
        llvm_target: "aarch64-unknown-linux-musl".to_string(),
        pointer_width: 64,
        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
        arch: "aarch64".to_string(),
        options: TargetOptions { mcount: "\u{1}_mcount".to_string(), ..base },
    }
}
<|endoftext|>