<commit_before>use std::mem;
use std::ptr;
use std::sync::{
    Arc,
    Mutex,
};
use std::thread;
use std::time::Duration;

use winapi::winsock2::{
    fd_set,
    SOCKET_ERROR,
    timeval,
    WSADATA,
};
use ws2_32::{
    select,
    WSACleanup,
    WSAStartup,
};

use c_ares;
use mio;

use error::ResolverError;
use eventloop::EventLoopHandle;

// The EventLoop will use select() to check on the status of file descriptors
// that c-ares cares about.
//
// It also waits for a message telling it to shut down.  We use a mio channel
// here only for consistency with the unix interface.
pub struct EventLoop {
    tx_msg_channel: mio::channel::Sender<Message>,
    rx_msg_channel: mio::channel::Receiver<Message>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: bool,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Shut down'.
    ShutDown,
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(options: c_ares::Options) -> Result<EventLoop, ResolverError> {
        // Initialize sockets.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the message channel.
        let (tx, rx) = mio::channel::channel();

        // Create the c-ares channel.
        let ares_channel = try!(c_ares::Channel::new(options));
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            tx_msg_channel: tx,
            rx_msg_channel: rx,
            ares_channel: locked_channel,
            quit: false,
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let tx_clone = self.tx_msg_channel.clone();
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, tx_clone)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let mut read_fds: fd_set = unsafe { mem::uninitialized() };
        let mut write_fds: fd_set = unsafe { mem::uninitialized() };

        // Loop round, asking c-ares what it cares about and doing as asked.
        loop {
            read_fds.fd_count = 0;
            write_fds.fd_count = 0;
            let count = self.ares_channel.lock().unwrap()
                .fds(&mut read_fds, &mut write_fds);

            if count == 0 {
                thread::sleep(Duration::from_millis(100));
            } else {
                let select_timeout = timeval {
                    tv_sec: 0,
                    tv_usec: 100000,
                };
                let results = unsafe {
                    select(
                        0,
                        &mut read_fds,
                        &mut write_fds,
                        ptr::null_mut(),
                        &select_timeout
                    )
                };

                // Process whatever happened.
                match results {
                    SOCKET_ERROR => panic!("Socket error"),
                    _ => self.ares_channel.lock().unwrap()
                        .process(&mut read_fds, &mut write_fds),
                }
            }

            // Check whether we've been asked to quit.
            self.handle_messages();
            if self.quit { break }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        // The only possible message is an instruction to shut down.
        if let Ok(Message::ShutDown) = self.rx_msg_channel.try_recv() {
            self.quit = true;
        }
    }
}

impl Drop for EventLoop {
    fn drop(&mut self) {
        unsafe { WSACleanup(); }
    }
}
<commit_msg>rename variable<commit_after>use std::mem;
use std::ptr;
use std::sync::{
    Arc,
    Mutex,
};
use std::thread;
use std::time::Duration;

use winapi::winsock2::{
    fd_set,
    SOCKET_ERROR,
    timeval,
    WSADATA,
};
use ws2_32::{
    select,
    WSACleanup,
    WSAStartup,
};

use c_ares;
use mio;

use error::ResolverError;
use eventloop::EventLoopHandle;

// The EventLoop will use select() to check on the status of file descriptors
// that c-ares cares about.
//
// It also waits for a message telling it to shut down.  We use a mio channel
// here only for consistency with the unix interface.
pub struct EventLoop {
    tx_msg_channel: mio::channel::Sender<Message>,
    rx_msg_channel: mio::channel::Receiver<Message>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: bool,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Shut down'.
    ShutDown,
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(options: c_ares::Options) -> Result<EventLoop, ResolverError> {
        // Initialize sockets.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the message channel.
        let (tx, rx) = mio::channel::channel();

        // Create the c-ares channel.
        let ares_channel = try!(c_ares::Channel::new(options));
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            tx_msg_channel: tx,
            rx_msg_channel: rx,
            ares_channel: locked_channel,
            quit: false,
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let tx_clone = self.tx_msg_channel.clone();
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, tx_clone)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let mut read_fds: fd_set = unsafe { mem::uninitialized() };
        let mut write_fds: fd_set = unsafe { mem::uninitialized() };

        // Loop round, asking c-ares what it cares about and doing as asked.
        loop {
            read_fds.fd_count = 0;
            write_fds.fd_count = 0;
            let count = self.ares_channel.lock().unwrap()
                .fds(&mut read_fds, &mut write_fds);

            if count == 0 {
                thread::sleep(Duration::from_millis(100));
            } else {
                let timeout = timeval {
                    tv_sec: 0,
                    tv_usec: 100000,
                };
                let results = unsafe {
                    select(
                        0,
                        &mut read_fds,
                        &mut write_fds,
                        ptr::null_mut(),
                        &timeout
                    )
                };

                // Process whatever happened.
                match results {
                    SOCKET_ERROR => panic!("Socket error"),
                    _ => self.ares_channel.lock().unwrap()
                        .process(&mut read_fds, &mut write_fds),
                }
            }

            // Check whether we've been asked to quit.
            self.handle_messages();
            if self.quit { break }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        // The only possible message is an instruction to shut down.
        if let Ok(Message::ShutDown) = self.rx_msg_channel.try_recv() {
            self.quit = true;
        }
    }
}

impl Drop for EventLoop {
    fn drop(&mut self) {
        unsafe { WSACleanup(); }
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::sync::{
    Arc,
    Mutex,
};
use std::thread;
use std::time::Duration;

use winapi::winsock2::{
    fd_set,
    FD_SETSIZE,
    SOCKET_ERROR,
    timeval,
    WSADATA,
};
use ws2_32::{
    select,
    WSACleanup,
    WSAStartup,
};

use c_ares;
use mio;

use error::ResolverError;
use eventloop::EventLoopHandle;

// The EventLoop will use select() to check on the status of file descriptors
// that c-ares cares about.
//
// It also waits for a message telling it to shut down.  We use a mio channel
// here only for consistency with the unix interface.
pub struct EventLoop {
    tx_msg_channel: mio::channel::Sender<Message>,
    rx_msg_channel: mio::channel::Receiver<Message>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: bool,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Shut down'.
    ShutDown,
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(options: c_ares::Options) -> Result<EventLoop, ResolverError> {
        // Initialize sockets.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the message channel.
        let (tx, rx) = mio::channel::channel();

        // Create the c-ares channel.
        let ares_channel = try!(c_ares::Channel::new(options));
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            tx_msg_channel: tx,
            rx_msg_channel: rx,
            ares_channel: locked_channel,
            quit: false,
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let tx_clone = self.tx_msg_channel.clone();
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, tx_clone)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let timeout = timeval {
            tv_sec: 0,
            tv_usec: 200000,
        };
        let duration = Duration::from_millis(200);

        // Loop round, asking c-ares what it cares about and doing as asked.
        loop {
            let mut read_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let mut write_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let count = self.ares_channel.lock().unwrap()
                .fds(&mut read_fds, &mut write_fds);

            // Wait for something to happen.
            let results = unsafe {
                if count == 0 {
                    thread::sleep(duration);
                    0
                } else {
                    select(
                        0,
                        &mut read_fds,
                        &mut write_fds,
                        ptr::null_mut(),
                        &timeout
                    )
                }
            };

            // Process whatever happened.
            match results {
                SOCKET_ERROR => panic!("Socket error"),
                _ => self.ares_channel.lock().unwrap()
                    .process(&mut read_fds, &mut write_fds),
            }

            // Check whether we're asked to quit.
            self.handle_messages();
            if self.quit { break }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        // The only possible message is an instruction to shut down.
        if let Ok(Message::ShutDown) = self.rx_msg_channel.try_recv() {
            self.quit = true;
        }
    }
}

impl Drop for EventLoop {
    fn drop(&mut self) {
        unsafe { WSACleanup(); }
    }
}
<commit_msg>don't reinitialize array unnecessarily<commit_after>use std::mem;
use std::ptr;
use std::sync::{
    Arc,
    Mutex,
};
use std::thread;
use std::time::Duration;

use winapi::winsock2::{
    fd_set,
    SOCKET_ERROR,
    timeval,
    WSADATA,
};
use ws2_32::{
    select,
    WSACleanup,
    WSAStartup,
};

use c_ares;
use mio;

use error::ResolverError;
use eventloop::EventLoopHandle;

// The EventLoop will use select() to check on the status of file descriptors
// that c-ares cares about.
//
// It also waits for a message telling it to shut down.  We use a mio channel
// here only for consistency with the unix interface.
pub struct EventLoop {
    tx_msg_channel: mio::channel::Sender<Message>,
    rx_msg_channel: mio::channel::Receiver<Message>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: bool,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Shut down'.
    ShutDown,
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(options: c_ares::Options) -> Result<EventLoop, ResolverError> {
        // Initialize sockets.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the message channel.
        let (tx, rx) = mio::channel::channel();

        // Create the c-ares channel.
        let ares_channel = try!(c_ares::Channel::new(options));
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            tx_msg_channel: tx,
            rx_msg_channel: rx,
            ares_channel: locked_channel,
            quit: false,
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let tx_clone = self.tx_msg_channel.clone();
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, tx_clone)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let timeout = timeval {
            tv_sec: 0,
            tv_usec: 200000,
        };
        let duration = Duration::from_millis(200);
        let mut read_fds: fd_set = unsafe { mem::uninitialized() };
        let mut write_fds: fd_set = unsafe { mem::uninitialized() };

        // Loop round, asking c-ares what it cares about and doing as asked.
        loop {
            read_fds.fd_count = 0;
            write_fds.fd_count = 0;
            let count = self.ares_channel.lock().unwrap()
                .fds(&mut read_fds, &mut write_fds);

            // Wait for something to happen.
            let results = unsafe {
                if count == 0 {
                    thread::sleep(duration);
                    0
                } else {
                    select(
                        0,
                        &mut read_fds,
                        &mut write_fds,
                        ptr::null_mut(),
                        &timeout
                    )
                }
            };

            // Process whatever happened.
            match results {
                SOCKET_ERROR => panic!("Socket error"),
                _ => self.ares_channel.lock().unwrap()
                    .process(&mut read_fds, &mut write_fds),
            }

            // Check whether we're asked to quit.
            self.handle_messages();
            if self.quit { break }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        // The only possible message is an instruction to shut down.
        if let Ok(Message::ShutDown) = self.rx_msg_channel.try_recv() {
            self.quit = true;
        }
    }
}

impl Drop for EventLoop {
    fn drop(&mut self) {
        unsafe { WSACleanup(); }
    }
}
<|endoftext|>


<commit_before>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

extern mod grust (name="grust", vers="0.1");
extern mod gio (name="grust-Gio", vers="2.0");

extern mod std;

use core::result::{Result,Ok};
use core::comm::{Port,stream};
use core::task::TaskResult;
use core::util;
use std::timer::sleep;
// use std::timer::recv_timeout;
use std::uv_global_loop;
use grust::eventloop::EventLoop;

// We have to do this because of an rpath problem with crates linking to
// foreign libraries
extern mod grustna {
}

// Test timeout in milliseconds
static TEST_TIMEOUT: uint = 3000u;

fn spawn_with_future(func: ~fn()) -> Port<TaskResult> {
    let mut (port, _) = stream::<TaskResult>();
    task::task()
        .future_result(|p| {
            port = p;
        })
        .spawn(func);
    port
}

fn tcase(test: ~fn()) {
    grust::init();

    let port = spawn_with_future(test);

    // recv_timeout is broken, see https://github.com/mozilla/rust/issues/6089
    match Some(port.recv()) /* recv_timeout(&uv_global_loop::get(), TEST_TIMEOUT, &port) */ {
        Some(task::Success) => {}
        Some(task::Failure) => {
            fail!(~"test failed");
        }
        None => {
            error!("test timed out");
            unsafe { libc::abort(); }
        }
    }
}

fn tcase_result(test: ~fn() -> Result<(),()>) {
    do tcase {
        let result = test();
        assert!(result == Ok(()));
    }
}

#[test]
fn simple() {
    do tcase {
        let fobj = gio::File::new_for_path("/dev/null");
        let f = fobj.interface() as &gio::File;
        assert!(f.get_path().to_str() == ~"/dev/null");
    }
}

#[test]
fn as_interface() {
    do tcase {
        gio::File::new_for_path("/dev/null").as_interface(|fobj| {
                let f = fobj as &gio::File;
                assert!(f.get_path().to_str() == ~"/dev/null");
            });
    }
}

#[test]
fn new_ref() {
    do tcase {
        let fobj = gio::File::new_for_path("/dev/null");
        let gobj = fobj.interface().new_ref();
        let g = gobj.interface() as &gio::File;
        assert!(g.get_path().to_str() == ~"/dev/null");
    }
}

#[test]
fn clone() {
    do tcase {
        let fobj = gio::File::new_for_path("/dev/null");
        fobj.clone().as_interface(|gobj| {
                let g = gobj as &gio::File;
                assert!(g.get_path().to_str() == ~"/dev/null");
            });
    }
}

#[test]
fn off_task() {
    do tcase_result {
        let f = ~gio::File::new_for_path("/dev/null");
        do task::try {
            let f = f.interface() as &gio::File;
            let p = f.get_path();
            assert!(p.to_str() == ~"/dev/null");
        }
    }
}

#[test]
fn off_task_as_interface() {
    do tcase_result {
        let fobj = ~gio::File::new_for_path("/dev/null");
        do task::try {
            fobj.as_interface(|fifa| {
                    let f = fifa as &gio::File;
                    let p = f.get_path();
                    assert!(p.to_str() == ~"/dev/null");
                });
        }
    }
}

#[test]
fn async() {
    do tcase {
        let fobj = gio::File::new_for_path("/dev/null");
        let f = fobj.interface() as &gio::File;
        let el = EventLoop::new();
        let elo = ~el.clone();
        f.read_async(0, None,
                |obj, res| {
                    let f: &gio::File = obj.cast::<gio::raw::GFile>()
                                        as &gio::File;
                    let in = f.read_finish(res);
                    util::ignore(in);
                    elo.quit();
                });
        el.run();
    }
}

#[test]
fn async_off_stack() {
    do tcase {
        let fobj = ~gio::File::new_for_path("/dev/null");
        let el = EventLoop::new();
        let elo = ~el.clone();
        task::spawn_sched(task::ThreadPerCore, || {
            let f = fobj.interface() as &gio::File;

            // Give the event loop time to start
            sleep(&uv_global_loop::get(), 100);

            let elo2 = ~elo.clone();
            f.read_async(0, None, |obj, res| {
                    let f = obj.cast::<gio::raw::GFile>() as &gio::File;
                    f.read_finish(res);
                    elo2.quit();
                });
        });
        el.run();
    }
}
<commit_msg>Don't really need to sleep for the event loop to start<commit_after>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

extern mod grust (name="grust", vers="0.1");
extern mod gio (name="grust-Gio", vers="2.0");

extern mod std;

use core::result::{Result,Ok};
use core::comm::{Port,stream};
use core::task::TaskResult;
use core::util;
// use std::timer::recv_timeout;
// use std::uv_global_loop;
use grust::eventloop::EventLoop;

// We have to do this because of an rpath problem with crates linking to
// foreign libraries
extern mod grustna {
}

// Test timeout in milliseconds
static TEST_TIMEOUT: uint = 3000u;

fn spawn_with_future(func: ~fn()) -> Port<TaskResult> {
    let mut (port, _) = stream::<TaskResult>();
    task::task()
        .future_result(|p| {
            port = p;
        })
        .spawn(func);
    port
}

fn tcase(test: ~fn()) {
    grust::init();

    let port = spawn_with_future(test);

    // recv_timeout is broken, see https://github.com/mozilla/rust/issues/6089
    match Some(port.recv()) /* recv_timeout(&uv_global_loop::get(), TEST_TIMEOUT, &port) */ {
        Some(task::Success) => {}
        Some(task::Failure) => {
            fail!(~"test failed");
        }
        None => {
            error!("test timed out");
            unsafe { libc::abort(); }
        }
    }
}

fn tcase_result(test: ~fn() -> Result<(),()>) {
    do tcase {
        let result = test();
        assert!(result == Ok(()));
    }
}

#[test]
fn simple() {
    do tcase {
        let fobj = gio::File::new_for_path("/dev/null");
        let f = fobj.interface() as &gio::File;
        assert!(f.get_path().to_str() == ~"/dev/null");
    }
}

#[test]
fn as_interface() {
    do tcase {
        gio::File::new_for_path("/dev/null").as_interface(|fobj| {
                let f = fobj as &gio::File;
                assert!(f.get_path().to_str() == ~"/dev/null");
            });
    }
}

#[test]
fn new_ref() {
    do tcase {
        let fobj = gio::File::new_for_path("/dev/null");
        let gobj = fobj.interface().new_ref();
        let g = gobj.interface() as &gio::File;
        assert!(g.get_path().to_str() == ~"/dev/null");
    }
}

#[test]
fn clone() {
    do tcase {
        let fobj = gio::File::new_for_path("/dev/null");
        fobj.clone().as_interface(|gobj| {
                let g = gobj as &gio::File;
                assert!(g.get_path().to_str() == ~"/dev/null");
            });
    }
}

#[test]
fn off_task() {
    do tcase_result {
        let f = ~gio::File::new_for_path("/dev/null");
        do task::try {
            let f = f.interface() as &gio::File;
            let p = f.get_path();
            assert!(p.to_str() == ~"/dev/null");
        }
    }
}

#[test]
fn off_task_as_interface() {
    do tcase_result {
        let fobj = ~gio::File::new_for_path("/dev/null");
        do task::try {
            fobj.as_interface(|fifa| {
                    let f = fifa as &gio::File;
                    let p = f.get_path();
                    assert!(p.to_str() == ~"/dev/null");
                });
        }
    }
}

#[test]
fn async() {
    do tcase {
        let fobj = gio::File::new_for_path("/dev/null");
        let f = fobj.interface() as &gio::File;
        let el = EventLoop::new();
        let elo = ~el.clone();
        f.read_async(0, None,
                |obj, res| {
                    let f: &gio::File = obj.cast::<gio::raw::GFile>()
                                        as &gio::File;
                    let in = f.read_finish(res);
                    util::ignore(in);
                    elo.quit();
                });
        el.run();
    }
}

#[test]
fn async_off_stack() {
    do tcase {
        let fobj = ~gio::File::new_for_path("/dev/null");
        let el = EventLoop::new();
        let elo = ~el.clone();
        task::spawn_sched(task::ThreadPerCore, || {
            let f = fobj.interface() as &gio::File;
            let elo2 = ~elo.clone();
            f.read_async(0, None, |obj, res| {
                    let f = obj.cast::<gio::raw::GFile>() as &gio::File;
                    f.read_finish(res);
                    elo2.quit();
                });
        });
        el.run();
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:expand-with-a-macro.rs

#![deny(warnings)]

#[macro_use]
extern crate expand_with_a_macro;

use std::panic;

#[derive(A)]
struct A;

fn main() {
    assert!(panic::catch_unwind(|| {
        A.a();
    }).is_err());
}

<commit_msg>tests: ignore wasm32 for run-pass/proc-macro/expand-with-a-macro.<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:expand-with-a-macro.rs

// ignore-wasm32-bare compiled with panic=abort by default

#![deny(warnings)]

#[macro_use]
extern crate expand_with_a_macro;

use std::panic;

#[derive(A)]
struct A;

fn main() {
    assert!(panic::catch_unwind(|| {
        A.a();
    }).is_err());
}

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{ColorF, LayerPoint, LayerRect, LayerSize, LayerVector2D};
use api::{BorderRadius, BoxShadowClipMode, LayoutSize, LayerPrimitiveInfo};
use api::{ClipMode, ClipAndScrollInfo, ComplexClipRegion, LocalClip};
use api::{PipelineId};
use app_units::Au;
use clip::ClipSource;
use frame_builder::FrameBuilder;
use gpu_types::BrushImageKind;
use prim_store::{PrimitiveContainer};
use prim_store::{BrushMaskKind, BrushKind, BrushPrimitive};
use picture::PicturePrimitive;
use util::RectHelpers;
use render_task::MAX_BLUR_STD_DEVIATION;

// The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels.
pub const BLUR_SAMPLE_SCALE: f32 = 3.0;

// Maximum blur radius.
// Taken from https://searchfox.org/mozilla-central/rev/c633ffa4c4611f202ca11270dcddb7b29edddff8/layout/painting/nsCSSRendering.cpp#4412
pub const MAX_BLUR_RADIUS : f32 = 300.;

// The amount of padding added to the border corner drawn in the box shadow
// mask. This ensures that we get a few pixels past the corner that can be
// blurred without being affected by the border radius.
pub const MASK_CORNER_PADDING: f32 = 4.0;

#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "capture", derive(Deserialize, Serialize))]
pub struct BoxShadowCacheKey {
    pub width: Au,
    pub height: Au,
    pub blur_radius: Au,
    pub spread_radius: Au,
    pub offset_x: Au,
    pub offset_y: Au,
    pub br_top_left_w: Au,
    pub br_top_left_h: Au,
    pub br_top_right_w: Au,
    pub br_top_right_h: Au,
    pub br_bottom_left_w: Au,
    pub br_bottom_left_h: Au,
    pub br_bottom_right_w: Au,
    pub br_bottom_right_h: Au,
    pub clip_mode: BoxShadowClipMode,
}

impl FrameBuilder {
    pub fn add_box_shadow(
        &mut self,
        pipeline_id: PipelineId,
        clip_and_scroll: ClipAndScrollInfo,
        prim_info: &LayerPrimitiveInfo,
        box_offset: &LayerVector2D,
        color: &ColorF,
        mut blur_radius: f32,
        spread_radius: f32,
        border_radius: BorderRadius,
        clip_mode: BoxShadowClipMode,
    ) {
        if color.a == 0.0 {
            return;
        }

        let (spread_amount, brush_clip_mode) = match clip_mode {
            BoxShadowClipMode::Outset => {
                (spread_radius, ClipMode::Clip)
            }
            BoxShadowClipMode::Inset => {
                (-spread_radius, ClipMode::ClipOut)
            }
        };

        blur_radius = f32::min(blur_radius, MAX_BLUR_RADIUS);
        let shadow_radius = adjust_border_radius_for_box_shadow(
            border_radius,
            spread_amount,
        );
        let shadow_rect = prim_info.rect
            .translate(box_offset)
            .inflate(spread_amount, spread_amount);

        if blur_radius == 0.0 {
            if box_offset.x == 0.0 && box_offset.y == 0.0 && spread_amount == 0.0 {
                return;
            }
            let mut clips = Vec::new();

            let fast_info = match clip_mode {
                BoxShadowClipMode::Outset => {
                    // TODO(gw): Add a fast path for ClipOut + zero border radius!
                    clips.push(ClipSource::new_rounded_rect(
                        prim_info.rect,
                        border_radius,
                        ClipMode::ClipOut
                    ));

                    LayerPrimitiveInfo::with_clip(
                        shadow_rect,
                        LocalClip::RoundedRect(
                            shadow_rect,
                            ComplexClipRegion::new(
                                shadow_rect,
                                shadow_radius,
                                ClipMode::Clip,
                            ),
                        ),
                    )
                }
                BoxShadowClipMode::Inset => {
                    clips.push(ClipSource::new_rounded_rect(
                        shadow_rect,
                        shadow_radius,
                        ClipMode::ClipOut
                    ));

                    LayerPrimitiveInfo::with_clip(
                        prim_info.rect,
                        LocalClip::RoundedRect(
                            prim_info.rect,
                            ComplexClipRegion::new(
                                prim_info.rect,
                                border_radius,
                                ClipMode::Clip
                            ),
                        ),
                    )
                }
            };

            self.add_primitive(
                clip_and_scroll,
                &fast_info,
                clips,
                PrimitiveContainer::Brush(
                    BrushPrimitive::new(BrushKind::Solid {
                            color: *color,
                        },
                        None,
                    )
                ),
            );
        } else {
            let blur_offset = BLUR_SAMPLE_SCALE * blur_radius;
            let mut extra_clips = vec![];

            let cache_key = BoxShadowCacheKey {
                width: Au::from_f32_px(shadow_rect.size.width),
                height: Au::from_f32_px(shadow_rect.size.height),
                blur_radius: Au::from_f32_px(blur_radius),
                spread_radius: Au::from_f32_px(spread_radius),
                offset_x: Au::from_f32_px(box_offset.x),
                offset_y: Au::from_f32_px(box_offset.y),
                br_top_left_w: Au::from_f32_px(border_radius.top_left.width),
                br_top_left_h: Au::from_f32_px(border_radius.top_left.height),
                br_top_right_w: Au::from_f32_px(border_radius.top_right.width),
                br_top_right_h: Au::from_f32_px(border_radius.top_right.height),
                br_bottom_left_w: Au::from_f32_px(border_radius.bottom_left.width),
                br_bottom_left_h: Au::from_f32_px(border_radius.bottom_left.height),
                br_bottom_right_w: Au::from_f32_px(border_radius.bottom_right.width),
                br_bottom_right_h: Au::from_f32_px(border_radius.bottom_right.height),
                clip_mode,
            };

            match clip_mode {
                BoxShadowClipMode::Outset => {
                    let mut width;
                    let mut height;
                    let brush_prim;
                    let corner_size = shadow_radius.is_uniform_size();
                    let mut image_kind;

                    if !shadow_rect.is_well_formed_and_nonempty() {
                        return;
                    }

                    // If the outset box shadow has a uniform corner side, we can
                    // just blur the top left corner, and stretch / mirror that
                    // across the primitive.
                    if let Some(corner_size) = corner_size {
                        image_kind = BrushImageKind::Mirror;
                        width = MASK_CORNER_PADDING + corner_size.width.max(BLUR_SAMPLE_SCALE * blur_radius);
                        height = MASK_CORNER_PADDING + corner_size.height.max(BLUR_SAMPLE_SCALE * blur_radius);

                        brush_prim = BrushPrimitive::new(
                            BrushKind::Mask {
                                clip_mode: brush_clip_mode,
                                kind: BrushMaskKind::Corner(corner_size),
                            },
                            None,
                        );
                    } else {
                        // Create a minimal size primitive mask to blur. In this
                        // case, we ensure the size of each corner is the same,
                        // to simplify the shader logic that stretches the blurred
                        // result across the primitive.
                        image_kind = BrushImageKind::NinePatch;
                        let max_width = shadow_radius.top_left.width
                                            .max(shadow_radius.bottom_left.width)
                                            .max(shadow_radius.top_right.width)
                                            .max(shadow_radius.bottom_right.width);
                        let max_height = shadow_radius.top_left.height
                                            .max(shadow_radius.bottom_left.height)
                                            .max(shadow_radius.top_right.height)
                                            .max(shadow_radius.bottom_right.height);

                        width = 2.0 * max_width + BLUR_SAMPLE_SCALE * blur_radius;
                        height = 2.0 * max_height + BLUR_SAMPLE_SCALE * blur_radius;

                        // If the width or height ends up being bigger than the original
                        // primitive shadow rect, just blur the entire rect and draw that
                        // as a simple blit.
                        if width > prim_info.rect.size.width || height > prim_info.rect.size.height {
                            image_kind = BrushImageKind::Simple;
                            width = prim_info.rect.size.width;
                            height = prim_info.rect.size.height;
                        }

                        let clip_rect = LayerRect::new(LayerPoint::zero(),
                                                       LayerSize::new(width, height));

                        brush_prim = BrushPrimitive::new(
                            BrushKind::Mask {
                                clip_mode: brush_clip_mode,
                                kind: BrushMaskKind::RoundedRect(clip_rect, shadow_radius),
                            },
                            None,
                        );
                    };

                    // Construct a mask primitive to add to the picture.
                    let brush_rect = LayerRect::new(LayerPoint::zero(),
                                                    LayerSize::new(width, height));
                    let brush_info = LayerPrimitiveInfo::new(brush_rect);
                    let brush_prim_index = self.create_primitive(
                        &brush_info,
                        Vec::new(),
                        PrimitiveContainer::Brush(brush_prim),
                    );

                    // Create a box shadow picture and add the mask primitive to it.
                    let pic_rect = shadow_rect.inflate(blur_offset, blur_offset);
                    let mut pic_prim = PicturePrimitive::new_box_shadow(
                        blur_radius,
                        *color,
                        clip_mode,
                        image_kind,
                        cache_key,
                        pipeline_id,
                    );
                    pic_prim.add_primitive(
                        brush_prim_index,
                        clip_and_scroll
                    );

                    extra_clips.push(ClipSource::new_rounded_rect(
                        prim_info.rect,
                        border_radius,
                        ClipMode::ClipOut,
                    ));

                    let pic_info = LayerPrimitiveInfo::new(pic_rect);
                    self.add_primitive(
                        clip_and_scroll,
                        &pic_info,
                        extra_clips,
                        PrimitiveContainer::Picture(pic_prim),
                    );
                }
                BoxShadowClipMode::Inset => {
                    // TODO(gw): Inset shadows still need an optimization pass.
                    //           We draw and blur way more pixels than needed.

                    // Draw a picture that covers the area of the primitive rect.
                    let brush_rect = LayerRect::new(
                        LayerPoint::zero(),
                        prim_info.rect.size
                    );

                    // Define where the inset box shadow rect is, local
                    // to the brush rect above.
                    let clip_rect = brush_rect.translate(box_offset)
                                              .inflate(spread_amount, spread_amount);

                    // Ensure there are more than one pixel around the edges, so that there
                    // is non-zero data to blur, in the case of an inset shadow
                    // with zero spread and zero offset.
                    // The size of inflation edge is determined by std deviation because large
                    // std deviation blur would be downscaled first. Thus, we need more thick
                    // edge to prevent edge get blurred after downscled.
                    let mut adjusted_blur_std_deviation = blur_radius * 0.5;
                    let mut inflate_size = 1.0;
                    while adjusted_blur_std_deviation > MAX_BLUR_STD_DEVIATION {
                        adjusted_blur_std_deviation *= 0.5;
                        inflate_size *= 2.0;
                    }

                    let brush_rect = brush_rect.inflate(inflate_size + box_offset.x.abs(), inflate_size + box_offset.y.abs());
                    let brush_prim = BrushPrimitive::new(
                        BrushKind::Mask {
                            clip_mode: brush_clip_mode,
                            kind: BrushMaskKind::RoundedRect(clip_rect, shadow_radius),
                        },
                        None,
                    );
                    let brush_info = LayerPrimitiveInfo::new(brush_rect);
                    let brush_prim_index = self.create_primitive(
                        &brush_info,
                        Vec::new(),
                        PrimitiveContainer::Brush(brush_prim),
                    );

                    // Create a box shadow picture primitive and add
                    // the brush primitive to it.
                    let mut pic_prim = PicturePrimitive::new_box_shadow(
                        blur_radius,
                        *color,
                        BoxShadowClipMode::Inset,
                        // TODO(gw): Make use of optimization for inset.
                        BrushImageKind::NinePatch,
                        cache_key,
                        pipeline_id,
                    );
                    pic_prim.add_primitive(
                        brush_prim_index,
                        clip_and_scroll
                    );

                    // Draw the picture one pixel outside the original
                    // rect to account for the inflate above. This
                    // extra edge will be clipped by the local clip
                    // rect set below.
                    let pic_rect = prim_info.rect.inflate(inflate_size + box_offset.x.abs(), inflate_size + box_offset.y.abs());
                    let pic_info = LayerPrimitiveInfo::with_clip_rect(
                        pic_rect,
                        prim_info.rect
                    );

                    // Add a normal clip to ensure nothing gets drawn
                    // outside the primitive rect.
                    if !border_radius.is_zero() {
                        extra_clips.push(ClipSource::new_rounded_rect(
                            prim_info.rect,
                            border_radius,
                            ClipMode::Clip,
                        ));
                    }

                    // Add the picture primitive to the frame.
                    self.add_primitive(
                        clip_and_scroll,
                        &pic_info,
                        extra_clips,
                        PrimitiveContainer::Picture(pic_prim),
                    );
                }
            }
        }
    }
}

fn adjust_border_radius_for_box_shadow(
    radius: BorderRadius,
    spread_amount: f32,
) -> BorderRadius {
    BorderRadius {
        top_left: adjust_corner_for_box_shadow(
            radius.top_left,
            spread_amount,
        ),
        top_right: adjust_corner_for_box_shadow(
            radius.top_right,
            spread_amount,
        ),
        bottom_right: adjust_corner_for_box_shadow(
            radius.bottom_right,
            spread_amount,
        ),
        bottom_left: adjust_corner_for_box_shadow(
            radius.bottom_left,
            spread_amount,
        ),
    }
}

fn adjust_corner_for_box_shadow(
    corner: LayoutSize,
    spread_amount: f32,
) -> LayoutSize {
    LayoutSize::new(
        adjust_radius_for_box_shadow(
            corner.width,
            spread_amount
        ),
        adjust_radius_for_box_shadow(
            corner.height,
            spread_amount
        ),
    )
}

fn adjust_radius_for_box_shadow(
    border_radius: f32,
    spread_amount: f32,
) -> f32 {
    if border_radius > 0.0 {
        (border_radius + spread_amount).max(0.0)
    } else {
        0.0
    }
}
<commit_msg>Fix incorrect border radius with outset shadows.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{ColorF, LayerPoint, LayerRect, LayerSize, LayerVector2D};
use api::{BorderRadius, BoxShadowClipMode, LayoutSize, LayerPrimitiveInfo};
use api::{ClipMode, ClipAndScrollInfo, ComplexClipRegion, LocalClip};
use api::{PipelineId};
use app_units::Au;
use clip::ClipSource;
use frame_builder::FrameBuilder;
use gpu_types::BrushImageKind;
use prim_store::{PrimitiveContainer};
use prim_store::{BrushMaskKind, BrushKind, BrushPrimitive};
use picture::PicturePrimitive;
use util::RectHelpers;
use render_task::MAX_BLUR_STD_DEVIATION;

// The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels.
pub const BLUR_SAMPLE_SCALE: f32 = 3.0;

// Maximum blur radius.
// Taken from https://searchfox.org/mozilla-central/rev/c633ffa4c4611f202ca11270dcddb7b29edddff8/layout/painting/nsCSSRendering.cpp#4412
pub const MAX_BLUR_RADIUS : f32 = 300.;

// The amount of padding added to the border corner drawn in the box shadow
// mask. This ensures that we get a few pixels past the corner that can be
// blurred without being affected by the border radius.
pub const MASK_CORNER_PADDING: f32 = 4.0;

#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "capture", derive(Deserialize, Serialize))]
pub struct BoxShadowCacheKey {
    pub width: Au,
    pub height: Au,
    pub blur_radius: Au,
    pub spread_radius: Au,
    pub offset_x: Au,
    pub offset_y: Au,
    pub br_top_left_w: Au,
    pub br_top_left_h: Au,
    pub br_top_right_w: Au,
    pub br_top_right_h: Au,
    pub br_bottom_left_w: Au,
    pub br_bottom_left_h: Au,
    pub br_bottom_right_w: Au,
    pub br_bottom_right_h: Au,
    pub clip_mode: BoxShadowClipMode,
}

impl FrameBuilder {
    pub fn add_box_shadow(
        &mut self,
        pipeline_id: PipelineId,
        clip_and_scroll: ClipAndScrollInfo,
        prim_info: &LayerPrimitiveInfo,
        box_offset: &LayerVector2D,
        color: &ColorF,
        mut blur_radius: f32,
        spread_radius: f32,
        border_radius: BorderRadius,
        clip_mode: BoxShadowClipMode,
    ) {
        if color.a == 0.0 {
            return;
        }

        let (spread_amount, brush_clip_mode) = match clip_mode {
            BoxShadowClipMode::Outset => {
                (spread_radius, ClipMode::Clip)
            }
            BoxShadowClipMode::Inset => {
                (-spread_radius, ClipMode::ClipOut)
            }
        };

        blur_radius = f32::min(blur_radius, MAX_BLUR_RADIUS);
        let shadow_radius = adjust_border_radius_for_box_shadow(
            border_radius,
            spread_amount,
        );
        let shadow_rect = prim_info.rect
            .translate(box_offset)
            .inflate(spread_amount, spread_amount);

        if blur_radius == 0.0 {
            if box_offset.x == 0.0 && box_offset.y == 0.0 && spread_amount == 0.0 {
                return;
            }
            let mut clips = Vec::new();

            let fast_info = match clip_mode {
                BoxShadowClipMode::Outset => {
                    // TODO(gw): Add a fast path for ClipOut + zero border radius!
                    clips.push(ClipSource::new_rounded_rect(
                        prim_info.rect,
                        border_radius,
                        ClipMode::ClipOut
                    ));

                    LayerPrimitiveInfo::with_clip(
                        shadow_rect,
                        LocalClip::RoundedRect(
                            shadow_rect,
                            ComplexClipRegion::new(
                                shadow_rect,
                                shadow_radius,
                                ClipMode::Clip,
                            ),
                        ),
                    )
                }
                BoxShadowClipMode::Inset => {
                    clips.push(ClipSource::new_rounded_rect(
                        shadow_rect,
                        shadow_radius,
                        ClipMode::ClipOut
                    ));

                    LayerPrimitiveInfo::with_clip(
                        prim_info.rect,
                        LocalClip::RoundedRect(
                            prim_info.rect,
                            ComplexClipRegion::new(
                                prim_info.rect,
                                border_radius,
                                ClipMode::Clip
                            ),
                        ),
                    )
                }
            };

            self.add_primitive(
                clip_and_scroll,
                &fast_info,
                clips,
                PrimitiveContainer::Brush(
                    BrushPrimitive::new(BrushKind::Solid {
                            color: *color,
                        },
                        None,
                    )
                ),
            );
        } else {
            let blur_offset = BLUR_SAMPLE_SCALE * blur_radius;
            let mut extra_clips = vec![];

            let cache_key = BoxShadowCacheKey {
                width: Au::from_f32_px(shadow_rect.size.width),
                height: Au::from_f32_px(shadow_rect.size.height),
                blur_radius: Au::from_f32_px(blur_radius),
                spread_radius: Au::from_f32_px(spread_radius),
                offset_x: Au::from_f32_px(box_offset.x),
                offset_y: Au::from_f32_px(box_offset.y),
                br_top_left_w: Au::from_f32_px(border_radius.top_left.width),
                br_top_left_h: Au::from_f32_px(border_radius.top_left.height),
                br_top_right_w: Au::from_f32_px(border_radius.top_right.width),
                br_top_right_h: Au::from_f32_px(border_radius.top_right.height),
                br_bottom_left_w: Au::from_f32_px(border_radius.bottom_left.width),
                br_bottom_left_h: Au::from_f32_px(border_radius.bottom_left.height),
                br_bottom_right_w: Au::from_f32_px(border_radius.bottom_right.width),
                br_bottom_right_h: Au::from_f32_px(border_radius.bottom_right.height),
                clip_mode,
            };

            match clip_mode {
                BoxShadowClipMode::Outset => {
                    let mut width;
                    let mut height;
                    let brush_prim;
                    let corner_size = shadow_radius.is_uniform_size();
                    let mut image_kind;

                    if !shadow_rect.is_well_formed_and_nonempty() {
                        return;
                    }

                    // If the outset box shadow has a uniform corner side, we can
                    // just blur the top left corner, and stretch / mirror that
                    // across the primitive.
                    if let Some(corner_size) = corner_size {
                        image_kind = BrushImageKind::Mirror;
                        width = MASK_CORNER_PADDING + corner_size.width.max(BLUR_SAMPLE_SCALE * blur_radius);
                        height = MASK_CORNER_PADDING + corner_size.height.max(BLUR_SAMPLE_SCALE * blur_radius);

                        brush_prim = BrushPrimitive::new(
                            BrushKind::Mask {
                                clip_mode: brush_clip_mode,
                                kind: BrushMaskKind::Corner(corner_size),
                            },
                            None,
                        );
                    } else {
                        // Create a minimal size primitive mask to blur. In this
                        // case, we ensure the size of each corner is the same,
                        // to simplify the shader logic that stretches the blurred
                        // result across the primitive.
                        image_kind = BrushImageKind::NinePatch;
                        let max_width = shadow_radius.top_left.width
                                            .max(shadow_radius.bottom_left.width)
                                            .max(shadow_radius.top_right.width)
                                            .max(shadow_radius.bottom_right.width);
                        let max_height = shadow_radius.top_left.height
                                            .max(shadow_radius.bottom_left.height)
                                            .max(shadow_radius.top_right.height)
                                            .max(shadow_radius.bottom_right.height);

                        width = 2.0 * max_width + BLUR_SAMPLE_SCALE * blur_radius;
                        height = 2.0 * max_height + BLUR_SAMPLE_SCALE * blur_radius;

                        // If the width or height ends up being bigger than the original
                        // primitive shadow rect, just blur the entire rect and draw that
                        // as a simple blit.
                        if width > prim_info.rect.size.width || height > prim_info.rect.size.height {
                            image_kind = BrushImageKind::Simple;
                            width = prim_info.rect.size.width + spread_amount * 2.0;
                            height = prim_info.rect.size.height + spread_amount * 2.0;
                        }

                        let clip_rect = LayerRect::new(
                            LayerPoint::zero(),
                            LayerSize::new(width, height)
                        );

                        brush_prim = BrushPrimitive::new(
                            BrushKind::Mask {
                                clip_mode: brush_clip_mode,
                                kind: BrushMaskKind::RoundedRect(clip_rect, shadow_radius),
                            },
                            None,
                        );
                    };

                    // Construct a mask primitive to add to the picture.
                    let brush_rect = LayerRect::new(LayerPoint::zero(),
                                                    LayerSize::new(width, height));
                    let brush_info = LayerPrimitiveInfo::new(brush_rect);
                    let brush_prim_index = self.create_primitive(
                        &brush_info,
                        Vec::new(),
                        PrimitiveContainer::Brush(brush_prim),
                    );

                    // Create a box shadow picture and add the mask primitive to it.
                    let pic_rect = shadow_rect.inflate(blur_offset, blur_offset);
                    let mut pic_prim = PicturePrimitive::new_box_shadow(
                        blur_radius,
                        *color,
                        clip_mode,
                        image_kind,
                        cache_key,
                        pipeline_id,
                    );
                    pic_prim.add_primitive(
                        brush_prim_index,
                        clip_and_scroll
                    );

                    extra_clips.push(ClipSource::new_rounded_rect(
                        prim_info.rect,
                        border_radius,
                        ClipMode::ClipOut,
                    ));

                    let pic_info = LayerPrimitiveInfo::new(pic_rect);
                    self.add_primitive(
                        clip_and_scroll,
                        &pic_info,
                        extra_clips,
                        PrimitiveContainer::Picture(pic_prim),
                    );
                }
                BoxShadowClipMode::Inset => {
                    // TODO(gw): Inset shadows still need an optimization pass.
                    //           We draw and blur way more pixels than needed.

                    // Draw a picture that covers the area of the primitive rect.
                    let brush_rect = LayerRect::new(
                        LayerPoint::zero(),
                        prim_info.rect.size
                    );

                    // Define where the inset box shadow rect is, local
                    // to the brush rect above.
                    let clip_rect = brush_rect.translate(box_offset)
                                              .inflate(spread_amount, spread_amount);

                    // Ensure there are more than one pixel around the edges, so that there
                    // is non-zero data to blur, in the case of an inset shadow
                    // with zero spread and zero offset.
                    // The size of inflation edge is determined by std deviation because large
                    // std deviation blur would be downscaled first. Thus, we need more thick
                    // edge to prevent edge get blurred after downscled.
                    let mut adjusted_blur_std_deviation = blur_radius * 0.5;
                    let mut inflate_size = 1.0;
                    while adjusted_blur_std_deviation > MAX_BLUR_STD_DEVIATION {
                        adjusted_blur_std_deviation *= 0.5;
                        inflate_size *= 2.0;
                    }

                    let brush_rect = brush_rect.inflate(inflate_size + box_offset.x.abs(), inflate_size + box_offset.y.abs());
                    let brush_prim = BrushPrimitive::new(
                        BrushKind::Mask {
                            clip_mode: brush_clip_mode,
                            kind: BrushMaskKind::RoundedRect(clip_rect, shadow_radius),
                        },
                        None,
                    );
                    let brush_info = LayerPrimitiveInfo::new(brush_rect);
                    let brush_prim_index = self.create_primitive(
                        &brush_info,
                        Vec::new(),
                        PrimitiveContainer::Brush(brush_prim),
                    );

                    // Create a box shadow picture primitive and add
                    // the brush primitive to it.
                    let mut pic_prim = PicturePrimitive::new_box_shadow(
                        blur_radius,
                        *color,
                        BoxShadowClipMode::Inset,
                        // TODO(gw): Make use of optimization for inset.
                        BrushImageKind::NinePatch,
                        cache_key,
                        pipeline_id,
                    );
                    pic_prim.add_primitive(
                        brush_prim_index,
                        clip_and_scroll
                    );

                    // Draw the picture one pixel outside the original
                    // rect to account for the inflate above. This
                    // extra edge will be clipped by the local clip
                    // rect set below.
                    let pic_rect = prim_info.rect.inflate(inflate_size + box_offset.x.abs(), inflate_size + box_offset.y.abs());
                    let pic_info = LayerPrimitiveInfo::with_clip_rect(
                        pic_rect,
                        prim_info.rect
                    );

                    // Add a normal clip to ensure nothing gets drawn
                    // outside the primitive rect.
                    if !border_radius.is_zero() {
                        extra_clips.push(ClipSource::new_rounded_rect(
                            prim_info.rect,
                            border_radius,
                            ClipMode::Clip,
                        ));
                    }

                    // Add the picture primitive to the frame.
                    self.add_primitive(
                        clip_and_scroll,
                        &pic_info,
                        extra_clips,
                        PrimitiveContainer::Picture(pic_prim),
                    );
                }
            }
        }
    }
}

fn adjust_border_radius_for_box_shadow(
    radius: BorderRadius,
    spread_amount: f32,
) -> BorderRadius {
    BorderRadius {
        top_left: adjust_corner_for_box_shadow(
            radius.top_left,
            spread_amount,
        ),
        top_right: adjust_corner_for_box_shadow(
            radius.top_right,
            spread_amount,
        ),
        bottom_right: adjust_corner_for_box_shadow(
            radius.bottom_right,
            spread_amount,
        ),
        bottom_left: adjust_corner_for_box_shadow(
            radius.bottom_left,
            spread_amount,
        ),
    }
}

fn adjust_corner_for_box_shadow(
    corner: LayoutSize,
    spread_amount: f32,
) -> LayoutSize {
    LayoutSize::new(
        adjust_radius_for_box_shadow(
            corner.width,
            spread_amount
        ),
        adjust_radius_for_box_shadow(
            corner.height,
            spread_amount
        ),
    )
}

fn adjust_radius_for_box_shadow(
    border_radius: f32,
    spread_amount: f32,
) -> f32 {
    if border_radius > 0.0 {
        (border_radius + spread_amount).max(0.0)
    } else {
        0.0
    }
}
<|endoftext|>


<commit_before>#![deny(unused_must_use)]

#[macro_use]
extern crate diesel;

use diesel::*;

table! {
    stuff (b) {
        b -> Bool,
    }
}

fn main() {
    use stuff::table as st;
    use stuff::b;

    st.select(b); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.select(b).distinct(); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.count(); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.order(b); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.limit(1); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.offset(1); //~ ERROR unused `diesel::query_builder::SelectStatement`

    st.filter(b.eq(true)); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.filter(b.eq(true)).limit(1); //~ ERROR unused `diesel::query_builder::SelectStatement`

    let _thingies = st.filter(b.eq(true)); // No ERROR
}
<commit_msg>Add tests for must_use statements<commit_after>#![deny(unused_must_use)]

#[macro_use]
extern crate diesel;

use diesel::*;

table! {
    stuff (b) {
        b -> Bool,
    }
}

fn main() {
    use stuff::table as st;
    use stuff::b;

    st.select(b); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.select(b).distinct(); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.count(); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.order(b); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.limit(1); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.offset(1); //~ ERROR unused `diesel::query_builder::SelectStatement`

    st.filter(b.eq(true)); //~ ERROR unused `diesel::query_builder::SelectStatement`
    st.filter(b.eq(true)).limit(1); //~ ERROR unused `diesel::query_builder::SelectStatement`

    insert_into(stuff)
        .values(b.eq(true)); //- ERROR unused `diesel::query_builder::InsertStatement`
    insert_into(stuff)
        .values(&vec![b.eq(true), b.eq(false)]); //~ ERROR unused `diesel::query_builder::InsertStatement`

    update(stuff).set(b.eq(true)); //~ ERROR unused `diesel::query_builder::UpdateStatement`

    delete(stuff); //~ ERROR unused `diesel::query_builder::DeleteStatement`

    let _thingies = st.filter(b.eq(true)); // No ERROR
}
<|endoftext|>


<commit_before>use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{
    def::{DefKind, Res},
    Item, ItemKind, PathSegment, UseKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::BytePos;

declare_clippy_lint! {
    /// **What it does:** Checks for `use Enum::*`.
    ///
    /// **Why is this bad?** It is usually better style to use the prefixed name of
    /// an enumeration variant, rather than importing variants.
    ///
    /// **Known problems:** Old-style enumerations that prefix the variants are
    /// still around.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// // Bad
    /// use std::cmp::Ordering::*;
    /// foo(Less);
    ///
    /// // Good
    /// use std::cmp::Ordering;
    /// foo(Ordering::Less)
    /// ```
    pub ENUM_GLOB_USE,
    pedantic,
    "use items that import all variants of an enum"
}

declare_clippy_lint! {
    /// **What it does:** Checks for wildcard imports `use _::*`.
    ///
    /// **Why is this bad?** wildcard imports can polute the namespace. This is especially bad if
    /// you try to import something through a wildcard, that already has been imported by name from
    /// a different source:
    ///
    /// ```rust,ignore
    /// use crate1::foo; // Imports a function named foo
    /// use crate2::*; // Has a function named foo
    ///
    /// foo(); // Calls crate1::foo
    /// ```
    ///
    /// This can lead to confusing error messages at best and to unexpected behavior at worst.
    ///
    /// **Exceptions:**
    ///
    /// Wildcard imports are allowed from modules named `prelude`. Many crates (including the standard library)
    /// provide modules named "prelude" specifically designed for wildcard import.
    ///
    /// `use super::*` is allowed in test modules. This is defined as any module with "test" in the name.
    ///
    /// These exceptions can be disabled using the `warn-on-all-wildcard-imports` configuration flag.
    ///
    /// **Known problems:** If macros are imported through the wildcard, this macro is not included
    /// by the suggestion and has to be added by hand.
    ///
    /// Applying the suggestion when explicit imports of the things imported with a glob import
    /// exist, may result in `unused_imports` warnings.
    ///
    /// **Example:**
    ///
    /// ```rust,ignore
    /// // Bad
    /// use crate1::*;
    ///
    /// foo();
    /// ```
    ///
    /// ```rust,ignore
    /// // Good
    /// use crate1::foo;
    ///
    /// foo();
    /// ```
    pub WILDCARD_IMPORTS,
    pedantic,
    "lint `use _::*` statements"
}

#[derive(Default)]
pub struct WildcardImports {
    warn_on_all: bool,
    test_modules_deep: u32,
}

impl WildcardImports {
    pub fn new(warn_on_all: bool) -> Self {
        Self {
            warn_on_all,
            test_modules_deep: 0,
        }
    }
}

impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]);

impl LateLintPass<'_, '_> for WildcardImports {
    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) {
        if is_test_module_or_function(item) {
            self.test_modules_deep = self.test_modules_deep.saturating_add(1);
        }
        if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() {
            return;
        }
        if_chain! {
            if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind;
            if self.warn_on_all || !self.check_exceptions(item, use_path.segments);
            let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner);
            if !used_imports.is_empty(); // Already handled by `unused_imports`
            then {
                let mut applicability = Applicability::MachineApplicable;
                let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability);
                let (span, braced_glob) = if import_source_snippet.is_empty() {
                    // This is a `_::{_, *}` import
                    // In this case `use_path.span` is empty and ends directly in front of the `*`,
                    // so we need to extend it by one byte.
                    (
                        use_path.span.with_hi(use_path.span.hi() + BytePos(1)),
                        true,
                    )
                } else {
                    // In this case, the `use_path.span` ends right before the `::*`, so we need to
                    // extend it up to the `*`. Since it is hard to find the `*` in weird
                    // formattings like `use _ ::  *;`, we extend it up to, but not including the
                    // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we
                    // can just use the end of the item span
                    let mut span = use_path.span.with_hi(item.span.hi());
                    if snippet(cx, span, "").ends_with(';') {
                        span = use_path.span.with_hi(item.span.hi() - BytePos(1));
                    }
                    (
                        span, false,
                    )
                };

                let imports_string = if used_imports.len() == 1 {
                    used_imports.iter().next().unwrap().to_string()
                } else {
                    let mut imports = used_imports
                        .iter()
                        .map(ToString::to_string)
                        .collect::<Vec<_>>();
                    imports.sort();
                    if braced_glob {
                        imports.join(", ")
                    } else {
                        format!("{{{}}}", imports.join(", "))
                    }
                };

                let sugg = if braced_glob {
                    imports_string
                } else {
                    format!("{}::{}", import_source_snippet, imports_string)
                };

                let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res {
                    (ENUM_GLOB_USE, "usage of wildcard import for enum variants")
                } else {
                    (WILDCARD_IMPORTS, "usage of wildcard import")
                };

                span_lint_and_sugg(
                    cx,
                    lint,
                    span,
                    message,
                    "try",
                    sugg,
                    applicability,
                );
            }
        }
    }

    fn check_item_post(&mut self, _: &LateContext<'_, '_>, item: &Item<'_>) {
        if is_test_module_or_function(item) {
            self.test_modules_deep = self.test_modules_deep.saturating_sub(1);
        }
    }
}

impl WildcardImports {
    fn check_exceptions(&self, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool {
        in_macro(item.span)
            || is_prelude_import(segments)
            || (is_super_only_import(segments) && self.test_modules_deep > 0)
    }
}

// Allow "...prelude::*" imports.
// Many crates have a prelude, and it is imported as a glob by design.
fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool {
    segments
        .iter()
        .last()
        .map_or(false, |ps| ps.ident.as_str() == "prelude")
}

// Allow "super::*" imports in tests.
fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool {
    segments.len() == 1 && segments[0].ident.as_str() == "super"
}

fn is_test_module_or_function(item: &Item<'_>) -> bool {
    matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
}
<commit_msg>Fix typo in wildcard_imports<commit_after>use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{
    def::{DefKind, Res},
    Item, ItemKind, PathSegment, UseKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::BytePos;

declare_clippy_lint! {
    /// **What it does:** Checks for `use Enum::*`.
    ///
    /// **Why is this bad?** It is usually better style to use the prefixed name of
    /// an enumeration variant, rather than importing variants.
    ///
    /// **Known problems:** Old-style enumerations that prefix the variants are
    /// still around.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// // Bad
    /// use std::cmp::Ordering::*;
    /// foo(Less);
    ///
    /// // Good
    /// use std::cmp::Ordering;
    /// foo(Ordering::Less)
    /// ```
    pub ENUM_GLOB_USE,
    pedantic,
    "use items that import all variants of an enum"
}

declare_clippy_lint! {
    /// **What it does:** Checks for wildcard imports `use _::*`.
    ///
    /// **Why is this bad?** wildcard imports can pollute the namespace. This is especially bad if
    /// you try to import something through a wildcard, that already has been imported by name from
    /// a different source:
    ///
    /// ```rust,ignore
    /// use crate1::foo; // Imports a function named foo
    /// use crate2::*; // Has a function named foo
    ///
    /// foo(); // Calls crate1::foo
    /// ```
    ///
    /// This can lead to confusing error messages at best and to unexpected behavior at worst.
    ///
    /// **Exceptions:**
    ///
    /// Wildcard imports are allowed from modules named `prelude`. Many crates (including the standard library)
    /// provide modules named "prelude" specifically designed for wildcard import.
    ///
    /// `use super::*` is allowed in test modules. This is defined as any module with "test" in the name.
    ///
    /// These exceptions can be disabled using the `warn-on-all-wildcard-imports` configuration flag.
    ///
    /// **Known problems:** If macros are imported through the wildcard, this macro is not included
    /// by the suggestion and has to be added by hand.
    ///
    /// Applying the suggestion when explicit imports of the things imported with a glob import
    /// exist, may result in `unused_imports` warnings.
    ///
    /// **Example:**
    ///
    /// ```rust,ignore
    /// // Bad
    /// use crate1::*;
    ///
    /// foo();
    /// ```
    ///
    /// ```rust,ignore
    /// // Good
    /// use crate1::foo;
    ///
    /// foo();
    /// ```
    pub WILDCARD_IMPORTS,
    pedantic,
    "lint `use _::*` statements"
}

#[derive(Default)]
pub struct WildcardImports {
    warn_on_all: bool,
    test_modules_deep: u32,
}

impl WildcardImports {
    pub fn new(warn_on_all: bool) -> Self {
        Self {
            warn_on_all,
            test_modules_deep: 0,
        }
    }
}

impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]);

impl LateLintPass<'_, '_> for WildcardImports {
    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) {
        if is_test_module_or_function(item) {
            self.test_modules_deep = self.test_modules_deep.saturating_add(1);
        }
        if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() {
            return;
        }
        if_chain! {
            if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind;
            if self.warn_on_all || !self.check_exceptions(item, use_path.segments);
            let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner);
            if !used_imports.is_empty(); // Already handled by `unused_imports`
            then {
                let mut applicability = Applicability::MachineApplicable;
                let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability);
                let (span, braced_glob) = if import_source_snippet.is_empty() {
                    // This is a `_::{_, *}` import
                    // In this case `use_path.span` is empty and ends directly in front of the `*`,
                    // so we need to extend it by one byte.
                    (
                        use_path.span.with_hi(use_path.span.hi() + BytePos(1)),
                        true,
                    )
                } else {
                    // In this case, the `use_path.span` ends right before the `::*`, so we need to
                    // extend it up to the `*`. Since it is hard to find the `*` in weird
                    // formattings like `use _ ::  *;`, we extend it up to, but not including the
                    // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we
                    // can just use the end of the item span
                    let mut span = use_path.span.with_hi(item.span.hi());
                    if snippet(cx, span, "").ends_with(';') {
                        span = use_path.span.with_hi(item.span.hi() - BytePos(1));
                    }
                    (
                        span, false,
                    )
                };

                let imports_string = if used_imports.len() == 1 {
                    used_imports.iter().next().unwrap().to_string()
                } else {
                    let mut imports = used_imports
                        .iter()
                        .map(ToString::to_string)
                        .collect::<Vec<_>>();
                    imports.sort();
                    if braced_glob {
                        imports.join(", ")
                    } else {
                        format!("{{{}}}", imports.join(", "))
                    }
                };

                let sugg = if braced_glob {
                    imports_string
                } else {
                    format!("{}::{}", import_source_snippet, imports_string)
                };

                let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res {
                    (ENUM_GLOB_USE, "usage of wildcard import for enum variants")
                } else {
                    (WILDCARD_IMPORTS, "usage of wildcard import")
                };

                span_lint_and_sugg(
                    cx,
                    lint,
                    span,
                    message,
                    "try",
                    sugg,
                    applicability,
                );
            }
        }
    }

    fn check_item_post(&mut self, _: &LateContext<'_, '_>, item: &Item<'_>) {
        if is_test_module_or_function(item) {
            self.test_modules_deep = self.test_modules_deep.saturating_sub(1);
        }
    }
}

impl WildcardImports {
    fn check_exceptions(&self, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool {
        in_macro(item.span)
            || is_prelude_import(segments)
            || (is_super_only_import(segments) && self.test_modules_deep > 0)
    }
}

// Allow "...prelude::*" imports.
// Many crates have a prelude, and it is imported as a glob by design.
fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool {
    segments
        .iter()
        .last()
        .map_or(false, |ps| ps.ident.as_str() == "prelude")
}

// Allow "super::*" imports in tests.
fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool {
    segments.len() == 1 && segments[0].ident.as_str() == "super"
}

fn is_test_module_or_function(item: &Item<'_>) -> bool {
    matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
}
<|endoftext|>