<commit_before>use std::env;
use std::ffi::{CStr, CString, OsStr, OsString};
use std::io::{Error as IoError, ErrorKind, Result as IoResult};
use std::os::raw::c_void;
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::os::unix::io::{IntoRawFd, RawFd};
use std::path::PathBuf;
use std::ptr;
use std::rc::Rc;

use wayland_commons::{Implementation, Interface};

use {Client, EventLoop, Global, LoopToken, NewResource};
use globals::global_bind;

#[cfg(feature = "native_lib")]
use wayland_sys::server::*;

pub(crate) struct DisplayInner {
    #[cfg(feature = "native_lib")]
    pub(crate) ptr: *mut wl_display,
}

impl Drop for DisplayInner {
    fn drop(&mut self) {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!();
        }
        #[cfg(feature = "native_lib")]
        {
            unsafe {
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_destroy, self.ptr);
            }
        }
    }
}

/// The wayland display
///
/// This is the core of your wayland server, this object must
/// be kept alive as long as your server is running. It allows
/// you to manage listening sockets and clients.
pub struct Display {
    inner: Rc<DisplayInner>,
}

impl Display {
    #[cfg(feature = "native_lib")]
    /// Create a new display
    ///
    /// This method provides you a `Display` as well as the main `EventLoop`
    /// which will host your clients' objects.
    ///
    /// Note that at this point, your server is not yet ready to receive connections,
    /// your need to add listening sockets using the `add_socket*` methods.
    pub fn new() -> (Display, EventLoop) {
        let ptr = unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) };

        let display = Display {
            inner: Rc::new(DisplayInner { ptr: ptr }),
        };

        // setup the client_created listener
        unsafe {
            let listener = signal::rust_listener_create(client_created);
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_display_add_client_created_listener,
                ptr,
                listener
            );
        }

        let evq_ptr = unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, ptr) };

        let evq = unsafe { EventLoop::display_new(display.inner.clone(), evq_ptr) };

        (display, evq)
    }

    /// Create a new global object
    ///
    /// This object will be advertized to all clients, and they will
    /// be able to instanciate it from their registries.
    ///
    /// Your implementation will be called whenever a client instanciates
    /// this global.
    ///
    /// The version specified is the **highest supported version**, you must
    /// be able to handle clients that choose to instanciate this global with
    /// a lower version number.
    pub fn create_global<I: Interface, Impl>(
        &mut self,
        _: &LoopToken,
        version: u32,
        implementation: Impl,
    ) -> Global<I>
    where
        Impl: Implementation<NewResource<I>, u32> + 'static,
    {
        let data = Box::new(Box::new(implementation) as Box<Implementation<NewResource<I>, u32>>);

        unsafe {
            let ptr = ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_global_create,
                self.inner.ptr,
                I::c_interface(),
                version as i32,
                &*data as *const Box<_> as *mut _,
                global_bind::<I>
            );

            Global::create(ptr, data)
        }
    }

    /// Flush events to the clients
    ///
    /// Will send as many pending events as possible to the respective sockets of the clients.
    /// Will not block, but might not send everything if the socket buffer fills up.
    pub fn flush_clients(&self) {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            unsafe {
                ffi_dispatch!(
                    WAYLAND_SERVER_HANDLE,
                    wl_display_flush_clients,
                    self.inner.ptr
                )
            };
        }
    }
}

#[cfg(feature = "native_lib")]
unsafe extern "C" fn client_created(_listener: *mut wl_listener, data: *mut c_void) {
    // init the client
    let _client = Client::from_ptr(data as *mut wl_client);
}

impl Display {
    /// Add a listening socket to this display
    ///
    /// Wayland clients will be able to connect to your compositor from this socket.
    ///
    /// Socket will be created in the directory specified by the environment variable
    /// `XDG_RUNTIME_DIR`.
    ///
    /// If a name is provided, it is used. Otherwise, if `WAYLAND_DISPLAY` environment
    /// variable is set, its contents are used as socket name. Otherwise, `wayland-0` is used.
    ///
    /// Errors if `name` contains an interior null, or if `XDG_RUNTIME_DIR` is not set,
    /// or if specified could not be bound (either it is already used or the compositor
    /// does not have the rights to create it).
    pub fn add_socket<S>(&mut self, name: Option<S>) -> IoResult<()>
    where
        S: AsRef<OsStr>,
    {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!();
        }
        #[cfg(feature = "native_lib")]
        {
            let cname = match name.as_ref().map(|s| CString::new(s.as_ref().as_bytes())) {
                Some(Ok(n)) => Some(n),
                Some(Err(_)) => {
                    return Err(IoError::new(
                        ErrorKind::InvalidInput,
                        "nulls are not allowed in socket name",
                    ))
                }
                None => None,
            };
            let ret = unsafe {
                ffi_dispatch!(
                    WAYLAND_SERVER_HANDLE,
                    wl_display_add_socket,
                    self.inner.ptr,
                    cname.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null())
                )
            };
            if ret == -1 {
                // lets try to be helpfull
                let mut socket_name = get_runtime_dir()?;
                match name {
                    Some(s) => socket_name.push(s.as_ref()),
                    None => socket_name.push("wayland-0"),
                }
                Err(IoError::new(
                    ErrorKind::PermissionDenied,
                    format!("could not bind socket {}", socket_name.to_string_lossy()),
                ))
            } else {
                Ok(())
            }
        }
    }

    /// Add an automatically named listening socket to this display
    ///
    /// Wayland clients will be able to connect to your compositor from this socket.
    ///
    /// Socket will be created in the directory specified by the environment variable
    /// `XDG_RUNTIME_DIR`. The directory is scanned for any name in the form `wayland-$d` with
    /// `0 <= $d < 32` and the first available one is used.
    ///
    /// Errors if `XDG_RUNTIME_DIR` is not set, or all 32 names are already in use.
    pub fn add_socket_auto(&mut self) -> IoResult<OsString> {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            let ret = unsafe {
                ffi_dispatch!(
                    WAYLAND_SERVER_HANDLE,
                    wl_display_add_socket_auto,
                    self.inner.ptr
                )
            };
            if ret.is_null() {
                // try to be helpfull
                let socket_name = get_runtime_dir()?;
                Err(IoError::new(
                    ErrorKind::Other,
                    format!(
                        "no available wayland-* name in {}",
                        socket_name.to_string_lossy()
                    ),
                ))
            } else {
                let sockname = unsafe { CStr::from_ptr(ret) };
                Ok(<OsString as OsStringExt>::from_vec(
                    sockname.to_bytes().into(),
                ))
            }
        }
    }

    /// Add existing listening socket to this display
    ///
    /// Wayland clients will be able to connect to your compositor from this socket.
    ///
    /// The existing socket fd must already be created, opened, and locked.
    /// The fd must be properly set to CLOEXEC and bound to a socket file
    /// with both bind() and listen() already called. An error is returned
    /// otherwise.
    pub fn add_socket_from<T>(&mut self, socket: T) -> IoResult<()>
    where
        T: IntoRawFd,
    {
        unsafe { self.add_socket_fd(socket.into_raw_fd()) }
    }

    /// Add existing listening socket to this display from a raw file descriptor
    ///
    /// Wayland clients will be able to connect to your compositor from this socket.
    ///
    /// The library takes ownership of the provided socket if this method returns
    /// successfully.
    ///
    /// The existing socket fd must already be created, opened, and locked.
    /// The fd must be properly set to CLOEXEC and bound to a socket file
    /// with both bind() and listen() already called. An error is returned
    /// otherwise.
    pub unsafe fn add_socket_fd(&mut self, fd: RawFd) -> IoResult<()> {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            let ret = ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_display_add_socket_fd,
                self.inner.ptr,
                fd
            );
            if ret == 0 {
                Ok(())
            } else {
                Err(IoError::new(ErrorKind::InvalidInput, "invalid socket fd"))
            }
        }
    }

    /// Create a new client to this display from an already-existing connected Fd
    pub unsafe fn create_client(&mut self, fd: RawFd) -> Client {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            let ret = ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_client_create,
                self.inner.ptr,
                fd
            );
            Client::from_ptr(ret)
        }
    }
}

#[cfg(feature = "native_lib")]
impl Display {
    /// Retrieve a pointer from the C lib to this `wl_display`
    pub fn c_ptr(&self) -> *mut wl_display {
        self.inner.ptr
    }
}

fn get_runtime_dir() -> IoResult<PathBuf> {
    match env::var_os("XDG_RUNTIME_DIR") {
        Some(s) => Ok(s.into()),
        None => Err(IoError::new(
            ErrorKind::NotFound,
            "XDG_RUNTIME_DIR env variable is not set",
        )),
    }
}
<commit_msg>cargo fmt<commit_after>use std::env;
use std::ffi::{CStr, CString, OsStr, OsString};
use std::io::{Error as IoError, ErrorKind, Result as IoResult};
use std::os::raw::c_void;
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::os::unix::io::{IntoRawFd, RawFd};
use std::path::PathBuf;
use std::ptr;
use std::rc::Rc;

use wayland_commons::{Implementation, Interface};

use {Client, EventLoop, Global, LoopToken, NewResource};
use globals::global_bind;

#[cfg(feature = "native_lib")]
use wayland_sys::server::*;

pub(crate) struct DisplayInner {
    #[cfg(feature = "native_lib")]
    pub(crate) ptr: *mut wl_display,
}

impl Drop for DisplayInner {
    fn drop(&mut self) {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!();
        }
        #[cfg(feature = "native_lib")]
        {
            unsafe {
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_destroy, self.ptr);
            }
        }
    }
}

/// The wayland display
///
/// This is the core of your wayland server, this object must
/// be kept alive as long as your server is running. It allows
/// you to manage listening sockets and clients.
pub struct Display {
    inner: Rc<DisplayInner>,
}

impl Display {
    #[cfg(feature = "native_lib")]
    /// Create a new display
    ///
    /// This method provides you a `Display` as well as the main `EventLoop`
    /// which will host your clients' objects.
    ///
    /// Note that at this point, your server is not yet ready to receive connections,
    /// your need to add listening sockets using the `add_socket*` methods.
    pub fn new() -> (Display, EventLoop) {
        let ptr = unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) };

        let display = Display {
            inner: Rc::new(DisplayInner { ptr: ptr }),
        };

        // setup the client_created listener
        unsafe {
            let listener = signal::rust_listener_create(client_created);
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_display_add_client_created_listener,
                ptr,
                listener
            );
        }

        let evq_ptr = unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, ptr) };

        let evq = unsafe { EventLoop::display_new(display.inner.clone(), evq_ptr) };

        (display, evq)
    }

    /// Create a new global object
    ///
    /// This object will be advertized to all clients, and they will
    /// be able to instanciate it from their registries.
    ///
    /// Your implementation will be called whenever a client instanciates
    /// this global.
    ///
    /// The version specified is the **highest supported version**, you must
    /// be able to handle clients that choose to instanciate this global with
    /// a lower version number.
    pub fn create_global<I: Interface, Impl>(
        &mut self,
        _: &LoopToken,
        version: u32,
        implementation: Impl,
    ) -> Global<I>
    where
        Impl: Implementation<NewResource<I>, u32> + 'static,
    {
        let data = Box::new(Box::new(implementation) as Box<Implementation<NewResource<I>, u32>>);

        unsafe {
            let ptr = ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_global_create,
                self.inner.ptr,
                I::c_interface(),
                version as i32,
                &*data as *const Box<_> as *mut _,
                global_bind::<I>
            );

            Global::create(ptr, data)
        }
    }

    /// Flush events to the clients
    ///
    /// Will send as many pending events as possible to the respective sockets of the clients.
    /// Will not block, but might not send everything if the socket buffer fills up.
    pub fn flush_clients(&self) {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            unsafe {
                ffi_dispatch!(
                    WAYLAND_SERVER_HANDLE,
                    wl_display_flush_clients,
                    self.inner.ptr
                )
            };
        }
    }
}

#[cfg(feature = "native_lib")]
unsafe extern "C" fn client_created(_listener: *mut wl_listener, data: *mut c_void) {
    // init the client
    let _client = Client::from_ptr(data as *mut wl_client);
}

impl Display {
    /// Add a listening socket to this display
    ///
    /// Wayland clients will be able to connect to your compositor from this socket.
    ///
    /// Socket will be created in the directory specified by the environment variable
    /// `XDG_RUNTIME_DIR`.
    ///
    /// If a name is provided, it is used. Otherwise, if `WAYLAND_DISPLAY` environment
    /// variable is set, its contents are used as socket name. Otherwise, `wayland-0` is used.
    ///
    /// Errors if `name` contains an interior null, or if `XDG_RUNTIME_DIR` is not set,
    /// or if specified could not be bound (either it is already used or the compositor
    /// does not have the rights to create it).
    pub fn add_socket<S>(&mut self, name: Option<S>) -> IoResult<()>
    where
        S: AsRef<OsStr>,
    {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!();
        }
        #[cfg(feature = "native_lib")]
        {
            let cname = match name.as_ref().map(|s| CString::new(s.as_ref().as_bytes())) {
                Some(Ok(n)) => Some(n),
                Some(Err(_)) => {
                    return Err(IoError::new(
                        ErrorKind::InvalidInput,
                        "nulls are not allowed in socket name",
                    ))
                }
                None => None,
            };
            let ret = unsafe {
                ffi_dispatch!(
                    WAYLAND_SERVER_HANDLE,
                    wl_display_add_socket,
                    self.inner.ptr,
                    cname.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null())
                )
            };
            if ret == -1 {
                // lets try to be helpfull
                let mut socket_name = get_runtime_dir()?;
                match name {
                    Some(s) => socket_name.push(s.as_ref()),
                    None => socket_name.push("wayland-0"),
                }
                Err(IoError::new(
                    ErrorKind::PermissionDenied,
                    format!("could not bind socket {}", socket_name.to_string_lossy()),
                ))
            } else {
                Ok(())
            }
        }
    }

    /// Add an automatically named listening socket to this display
    ///
    /// Wayland clients will be able to connect to your compositor from this socket.
    ///
    /// Socket will be created in the directory specified by the environment variable
    /// `XDG_RUNTIME_DIR`. The directory is scanned for any name in the form `wayland-$d` with
    /// `0 <= $d < 32` and the first available one is used.
    ///
    /// Errors if `XDG_RUNTIME_DIR` is not set, or all 32 names are already in use.
    pub fn add_socket_auto(&mut self) -> IoResult<OsString> {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            let ret = unsafe {
                ffi_dispatch!(
                    WAYLAND_SERVER_HANDLE,
                    wl_display_add_socket_auto,
                    self.inner.ptr
                )
            };
            if ret.is_null() {
                // try to be helpfull
                let socket_name = get_runtime_dir()?;
                Err(IoError::new(
                    ErrorKind::Other,
                    format!(
                        "no available wayland-* name in {}",
                        socket_name.to_string_lossy()
                    ),
                ))
            } else {
                let sockname = unsafe { CStr::from_ptr(ret) };
                Ok(<OsString as OsStringExt>::from_vec(
                    sockname.to_bytes().into(),
                ))
            }
        }
    }

    /// Add existing listening socket to this display
    ///
    /// Wayland clients will be able to connect to your compositor from this socket.
    ///
    /// The existing socket fd must already be created, opened, and locked.
    /// The fd must be properly set to CLOEXEC and bound to a socket file
    /// with both bind() and listen() already called. An error is returned
    /// otherwise.
    pub fn add_socket_from<T>(&mut self, socket: T) -> IoResult<()>
    where
        T: IntoRawFd,
    {
        unsafe { self.add_socket_fd(socket.into_raw_fd()) }
    }

    /// Add existing listening socket to this display from a raw file descriptor
    ///
    /// Wayland clients will be able to connect to your compositor from this socket.
    ///
    /// The library takes ownership of the provided socket if this method returns
    /// successfully.
    ///
    /// The existing socket fd must already be created, opened, and locked.
    /// The fd must be properly set to CLOEXEC and bound to a socket file
    /// with both bind() and listen() already called. An error is returned
    /// otherwise.
    pub unsafe fn add_socket_fd(&mut self, fd: RawFd) -> IoResult<()> {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            let ret = ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_display_add_socket_fd,
                self.inner.ptr,
                fd
            );
            if ret == 0 {
                Ok(())
            } else {
                Err(IoError::new(ErrorKind::InvalidInput, "invalid socket fd"))
            }
        }
    }

    /// Create a new client to this display from an already-existing connected Fd
    pub unsafe fn create_client(&mut self, fd: RawFd) -> Client {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            let ret = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_create, self.inner.ptr, fd);
            Client::from_ptr(ret)
        }
    }
}

#[cfg(feature = "native_lib")]
impl Display {
    /// Retrieve a pointer from the C lib to this `wl_display`
    pub fn c_ptr(&self) -> *mut wl_display {
        self.inner.ptr
    }
}

fn get_runtime_dir() -> IoResult<PathBuf> {
    match env::var_os("XDG_RUNTIME_DIR") {
        Some(s) => Ok(s.into()),
        None => Err(IoError::new(
            ErrorKind::NotFound,
            "XDG_RUNTIME_DIR env variable is not set",
        )),
    }
}
<|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 cssparser::Parser;
use media_queries::CSSErrorReporterTest;
use style::parser::ParserContext;
use style::stylesheets::Origin;
use style::values::specified::image::*;
use url::Url;

#[test]
fn test_radial_gradient() {
    // Parsing with all values
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(circle closest-side at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(ellipse closest-side at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-side circle at 20px 30px, red, green)",
                                                 "radial-gradient(circle closest-side at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-side ellipse at 20px 30px, red, green)",
                                                 "radial-gradient(ellipse closest-side at 20px 30px, red, green)");

    // Parsing with <shape-keyword> and <size> reversed
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-side circle at 20px 30px, red, green)",
                                                 "radial-gradient(circle closest-side at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-corner ellipse at 20px 30px, red, green)",
                                                 "radial-gradient(ellipse closest-corner at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(30px circle, red, green)",
                                                 "radial-gradient(circle 30px at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(30px 40px ellipse, red, green)",
                                                 "radial-gradient(ellipse 30px 40px at center center, red, green)");

    // Parsing without <size>
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(circle, red, green)",
                                   "radial-gradient(circle farthest-corner at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(ellipse, red, green)",
                                   "radial-gradient(ellipse farthest-corner at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(circle at 20px 30px, red, green)",
                                   "radial-gradient(circle farthest-corner at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(ellipse at 20px 30px, red, green)",
                                   "radial-gradient(ellipse farthest-corner at 20px 30px, red, green)");

    // Parsing without <shape-keyword>
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(20px at 20px 30px, red, green)",
                                   "radial-gradient(circle 20px at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(20px 30px at left center, red, green)",
                                   "radial-gradient(ellipse 20px 30px at left center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(closest-side at center, red, green)",
                                   "radial-gradient(ellipse closest-side at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(20px, red, green)",
                                   "radial-gradient(circle 20px at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(20px 30px, red, green)",
                                   "radial-gradient(ellipse 20px 30px at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(closest-side, red, green)",
                                   "radial-gradient(ellipse closest-side at center center, red, green)");

    // Parsing without <shape-keyword> and <size>
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(at center, red, green)",
                                   "radial-gradient(ellipse farthest-corner at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(at center bottom, red, green)",
                                   "radial-gradient(ellipse farthest-corner at center bottom, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(at 40px 50px, red, green)",
                                   "radial-gradient(ellipse farthest-corner at 40px 50px, red, green)");

    // Parsing with just color stops
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(red, green)",
                                   "radial-gradient(ellipse farthest-corner at center center, red, green)");

    // Parsing repeating radial gradient
    assert_roundtrip_with_context!(Image::parse,
                                   "repeating-radial-gradient(red, green)",
                                   "repeating-radial-gradient(ellipse farthest-corner at center center, red, green)");
}
<commit_msg>Adds parsing test for linear-gradient<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 cssparser::Parser;
use media_queries::CSSErrorReporterTest;
use style::parser::ParserContext;
use style::stylesheets::Origin;
use style::values::specified::image::*;
use url::Url;

#[test]
fn test_linear_gradient() {
    // Parsing from the right
    assert_roundtrip_with_context!(Image::parse, "linear-gradient(to left, red, green)",
                                                 "linear-gradient(4.712389rad, red, green)");

    // Parsing from the left
    assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right, red, green)",
                                                 "linear-gradient(1.5707964rad, red, green)");

    // Parsing with two values for <side-or-corner>
    assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right top, red, green)");

    // Parsing with <angle>
    assert_roundtrip_with_context!(Image::parse, "linear-gradient(45deg, red, green)",
                                                 "linear-gradient(0.7853982rad, red, green)");

   // Parsing with more than two entries in <color-stop-list>
   assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, yellow, green)",
                                                "linear-gradient(3.1415927rad, red, yellow, green)");

   // Parsing with percentage in the <color-stop-list>
   assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green, yellow 50%)",
                                                "linear-gradient(3.1415927rad, red, green, yellow 50%)");

    // Parsing without <angle> and <side-or-corner>
    assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green)",
                                                 "linear-gradient(3.1415927rad, red, green)");
}

#[test]
fn test_radial_gradient() {
    // Parsing with all values
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(circle closest-side at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(ellipse closest-side at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-side circle at 20px 30px, red, green)",
                                                 "radial-gradient(circle closest-side at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-side ellipse at 20px 30px, red, green)",
                                                 "radial-gradient(ellipse closest-side at 20px 30px, red, green)");

    // Parsing with <shape-keyword> and <size> reversed
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-side circle at 20px 30px, red, green)",
                                                 "radial-gradient(circle closest-side at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-corner ellipse at 20px 30px, red, green)",
                                                 "radial-gradient(ellipse closest-corner at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(30px circle, red, green)",
                                                 "radial-gradient(circle 30px at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse, "radial-gradient(30px 40px ellipse, red, green)",
                                                 "radial-gradient(ellipse 30px 40px at center center, red, green)");

    // Parsing without <size>
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(circle, red, green)",
                                   "radial-gradient(circle farthest-corner at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(ellipse, red, green)",
                                   "radial-gradient(ellipse farthest-corner at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(circle at 20px 30px, red, green)",
                                   "radial-gradient(circle farthest-corner at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(ellipse at 20px 30px, red, green)",
                                   "radial-gradient(ellipse farthest-corner at 20px 30px, red, green)");

    // Parsing without <shape-keyword>
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(20px at 20px 30px, red, green)",
                                   "radial-gradient(circle 20px at 20px 30px, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(20px 30px at left center, red, green)",
                                   "radial-gradient(ellipse 20px 30px at left center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(closest-side at center, red, green)",
                                   "radial-gradient(ellipse closest-side at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(20px, red, green)",
                                   "radial-gradient(circle 20px at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(20px 30px, red, green)",
                                   "radial-gradient(ellipse 20px 30px at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(closest-side, red, green)",
                                   "radial-gradient(ellipse closest-side at center center, red, green)");

    // Parsing without <shape-keyword> and <size>
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(at center, red, green)",
                                   "radial-gradient(ellipse farthest-corner at center center, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(at center bottom, red, green)",
                                   "radial-gradient(ellipse farthest-corner at center bottom, red, green)");
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(at 40px 50px, red, green)",
                                   "radial-gradient(ellipse farthest-corner at 40px 50px, red, green)");

    // Parsing with just color stops
    assert_roundtrip_with_context!(Image::parse,
                                   "radial-gradient(red, green)",
                                   "radial-gradient(ellipse farthest-corner at center center, red, green)");

    // Parsing repeating radial gradient
    assert_roundtrip_with_context!(Image::parse,
                                   "repeating-radial-gradient(red, green)",
                                   "repeating-radial-gradient(ellipse farthest-corner at center center, red, green)");
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

// compile-flags: -Z parse-only
// must-compile-successfully

#![feature(generic_associated_types)]

impl<T> Baz for T where T: Foo {
    //FIXME(sunjay): This should parse successfully
    type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
}

fn main() {}
<commit_msg>Removed FIXME on a line that actually works for some reason...<commit_after>// Copyright 2012 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.

// compile-flags: -Z parse-only
// must-compile-successfully

#![feature(generic_associated_types)]

impl<T> Baz for T where T: Foo {
    type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
}

fn main() {}
<|endoftext|>


<commit_before>// Copyright (C) 2021, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use serde::Deserialize;
use serde::Serialize;

use super::Bytes;

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum KeyType {
    ServerInitialSecret,
    ClientInitialSecret,

    ServerHandshakeSecret,
    ClientHandshakeSecret,

    #[serde(rename = "server_0rtt_secret")]
    Server0RttSecret,
    #[serde(rename = "client_0rtt_secret")]
    Client0RttSecret,
    #[serde(rename = "server_1rtt_secret")]
    Server1RttSecret,
    #[serde(rename = "client_1rtt_secret")]
    Client1RttSecret,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct KeyUpdated {
    key_type: KeyType,
    old: Option<Bytes>,
    new: Bytes,
    generation: Option<u32>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct KeyRetired {
    key_type: KeyType,
    key: Option<Bytes>,
    generation: Option<u32>,
}
<commit_msg>qlog: KeyUpdated new field is optional<commit_after>// Copyright (C) 2021, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use serde::Deserialize;
use serde::Serialize;

use super::Bytes;

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum KeyType {
    ServerInitialSecret,
    ClientInitialSecret,

    ServerHandshakeSecret,
    ClientHandshakeSecret,

    #[serde(rename = "server_0rtt_secret")]
    Server0RttSecret,
    #[serde(rename = "client_0rtt_secret")]
    Client0RttSecret,
    #[serde(rename = "server_1rtt_secret")]
    Server1RttSecret,
    #[serde(rename = "client_1rtt_secret")]
    Client1RttSecret,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct KeyUpdated {
    key_type: KeyType,
    old: Option<Bytes>,
    new: Option<Bytes>,
    generation: Option<u32>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct KeyRetired {
    key_type: KeyType,
    key: Option<Bytes>,
    generation: Option<u32>,
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]
extern crate libc;

fn main() {
    let mut buf = [0u8; 5];
    unsafe {
        libc::syscall(libc::SYS_getrandom, &mut buf as &mut [u8] as *mut [u8] as *mut u8 as *mut libc::c_void, 5, 0);
        //~^ ERROR constant evaluation error: miri does not support random number generators in deterministic mode!
    }
}
<commit_msg>Simplify cast using as_mut_ptr()<commit_after>#![feature(rustc_private)]
extern crate libc;

fn main() {
    let mut buf = [0u8; 5];
    unsafe {
        libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr() as *mut libc::c_void, 5, 0);
        //~^ ERROR constant evaluation error: miri does not support random number generators in deterministic mode!
    }
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

mod analysis_stats;
mod analysis_bench;
mod help;
mod progress_report;

use std::{error::Error, fmt::Write, io::Read};

use pico_args::Arguments;
use ra_ide::{file_structure, Analysis};
use ra_prof::profile;
use ra_syntax::{AstNode, SourceFile};

type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;

#[derive(Clone, Copy)]
pub enum Verbosity {
    Spammy,
    Verbose,
    Normal,
    Quiet,
}

impl Verbosity {
    fn is_verbose(self) -> bool {
        match self {
            Verbosity::Verbose | Verbosity::Spammy => true,
            _ => false,
        }
    }
    fn is_spammy(self) -> bool {
        match self {
            Verbosity::Spammy => true,
            _ => false,
        }
    }
}

fn main() -> Result<()> {
    env_logger::try_init()?;

    let subcommand = match std::env::args_os().nth(1) {
        None => {
            eprintln!("{}", help::GLOBAL_HELP);
            return Ok(());
        }
        Some(s) => s,
    };
    let mut matches = Arguments::from_vec(std::env::args_os().skip(2).collect());

    match &*subcommand.to_string_lossy() {
        "parse" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::PARSE_HELP);
                return Ok(());
            }
            let no_dump = matches.contains("--no-dump");
            matches.finish().or_else(handle_extra_flags)?;

            let _p = profile("parsing");
            let file = file()?;
            if !no_dump {
                println!("{:#?}", file.syntax());
            }
            std::mem::forget(file);
        }
        "symbols" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::SYMBOLS_HELP);
                return Ok(());
            }
            matches.finish().or_else(handle_extra_flags)?;
            let file = file()?;
            for s in file_structure(&file) {
                println!("{:?}", s);
            }
        }
        "highlight" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::HIGHLIGHT_HELP);
                return Ok(());
            }
            let rainbow_opt = matches.contains(["-r", "--rainbow"]);
            matches.finish().or_else(handle_extra_flags)?;
            let (analysis, file_id) = Analysis::from_single_file(read_stdin()?);
            let html = analysis.highlight_as_html(file_id, rainbow_opt).unwrap();
            println!("{}", html);
        }
        "analysis-stats" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::ANALYSIS_STATS_HELP);
                return Ok(());
            }
            let verbosity = match (
                matches.contains(["-vv", "--spammy"]),
                matches.contains(["-v", "--verbose"]),
                matches.contains(["-q", "--quiet"]),
            ) {
                (true, _, true) => Err("Invalid flags: -q conflicts with -vv")?,
                (true, _, false) => Verbosity::Spammy,
                (false, false, false) => Verbosity::Normal,
                (false, false, true) => Verbosity::Quiet,
                (false, true, false) => Verbosity::Verbose,
                (false, true, true) => Err("Invalid flags: -q conflicts with -v")?,
            };
            let randomize = matches.contains("--randomize");
            let memory_usage = matches.contains("--memory-usage");
            let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?;
            let with_deps: bool = matches.contains("--with-deps");
            let path = {
                let mut trailing = matches.free()?;
                if trailing.len() != 1 {
                    eprintln!("{}", help::ANALYSIS_STATS_HELP);
                    Err("Invalid flags")?;
                }
                trailing.pop().unwrap()
            };
            analysis_stats::run(
                verbosity,
                memory_usage,
                path.as_ref(),
                only.as_ref().map(String::as_ref),
                with_deps,
                randomize,
            )?;
        }
        "analysis-bench" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::ANALYSIS_BENCH_HELP);
                return Ok(());
            }
            let verbose = matches.contains(["-v", "--verbose"]);
            let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default();
            let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?;
            let complete_path: Option<String> = matches.opt_value_from_str("--complete")?;
            let goto_def_path: Option<String> = matches.opt_value_from_str("--goto-def")?;
            let op = match (highlight_path, complete_path, goto_def_path) {
                (Some(path), None, None) => analysis_bench::Op::Highlight { path: path.into() },
                (None, Some(position), None) => analysis_bench::Op::Complete(position.parse()?),
                (None, None, Some(position)) => analysis_bench::Op::GotoDef(position.parse()?),
                _ => panic!(
                    "exactly one of  `--highlight`, `--complete` or `--goto-def` must be set"
                ),
            };
            matches.finish().or_else(handle_extra_flags)?;
            analysis_bench::run(verbose, path.as_ref(), op)?;
        }
        _ => eprintln!("{}", help::GLOBAL_HELP),
    }
    Ok(())
}

fn handle_extra_flags(e: pico_args::Error) -> Result<()> {
    if let pico_args::Error::UnusedArgsLeft(flags) = e {
        let mut invalid_flags = String::new();
        for flag in flags {
            write!(&mut invalid_flags, "{}, ", flag)?;
        }
        let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2);
        Err(format!("Invalid flags: {}", invalid_flags).into())
    } else {
        Err(e.to_string().into())
    }
}

fn file() -> Result<SourceFile> {
    let text = read_stdin()?;
    Ok(SourceFile::parse(&text).tree())
}

fn read_stdin() -> Result<String> {
    let mut buff = String::new();
    std::io::stdin().read_to_string(&mut buff)?;
    Ok(buff)
}
<commit_msg>Use Arguments::from_os<commit_after>//! FIXME: write short doc here

mod analysis_stats;
mod analysis_bench;
mod help;
mod progress_report;

use std::{error::Error, fmt::Write, io::Read};

use pico_args::Arguments;
use ra_ide::{file_structure, Analysis};
use ra_prof::profile;
use ra_syntax::{AstNode, SourceFile};

type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;

#[derive(Clone, Copy)]
pub enum Verbosity {
    Spammy,
    Verbose,
    Normal,
    Quiet,
}

impl Verbosity {
    fn is_verbose(self) -> bool {
        match self {
            Verbosity::Verbose | Verbosity::Spammy => true,
            _ => false,
        }
    }
    fn is_spammy(self) -> bool {
        match self {
            Verbosity::Spammy => true,
            _ => false,
        }
    }
}

fn main() -> Result<()> {
    env_logger::try_init()?;

    let mut matches = Arguments::from_env();
    let subcommand = matches.subcommand()?.unwrap_or_default();

    match subcommand.as_str() {
        "parse" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::PARSE_HELP);
                return Ok(());
            }
            let no_dump = matches.contains("--no-dump");
            matches.finish().or_else(handle_extra_flags)?;

            let _p = profile("parsing");
            let file = file()?;
            if !no_dump {
                println!("{:#?}", file.syntax());
            }
            std::mem::forget(file);
        }
        "symbols" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::SYMBOLS_HELP);
                return Ok(());
            }
            matches.finish().or_else(handle_extra_flags)?;
            let file = file()?;
            for s in file_structure(&file) {
                println!("{:?}", s);
            }
        }
        "highlight" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::HIGHLIGHT_HELP);
                return Ok(());
            }
            let rainbow_opt = matches.contains(["-r", "--rainbow"]);
            matches.finish().or_else(handle_extra_flags)?;
            let (analysis, file_id) = Analysis::from_single_file(read_stdin()?);
            let html = analysis.highlight_as_html(file_id, rainbow_opt).unwrap();
            println!("{}", html);
        }
        "analysis-stats" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::ANALYSIS_STATS_HELP);
                return Ok(());
            }
            let verbosity = match (
                matches.contains(["-vv", "--spammy"]),
                matches.contains(["-v", "--verbose"]),
                matches.contains(["-q", "--quiet"]),
            ) {
                (true, _, true) => Err("Invalid flags: -q conflicts with -vv")?,
                (true, _, false) => Verbosity::Spammy,
                (false, false, false) => Verbosity::Normal,
                (false, false, true) => Verbosity::Quiet,
                (false, true, false) => Verbosity::Verbose,
                (false, true, true) => Err("Invalid flags: -q conflicts with -v")?,
            };
            let randomize = matches.contains("--randomize");
            let memory_usage = matches.contains("--memory-usage");
            let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?;
            let with_deps: bool = matches.contains("--with-deps");
            let path = {
                let mut trailing = matches.free()?;
                if trailing.len() != 1 {
                    eprintln!("{}", help::ANALYSIS_STATS_HELP);
                    Err("Invalid flags")?;
                }
                trailing.pop().unwrap()
            };
            analysis_stats::run(
                verbosity,
                memory_usage,
                path.as_ref(),
                only.as_ref().map(String::as_ref),
                with_deps,
                randomize,
            )?;
        }
        "analysis-bench" => {
            if matches.contains(["-h", "--help"]) {
                eprintln!("{}", help::ANALYSIS_BENCH_HELP);
                return Ok(());
            }
            let verbose = matches.contains(["-v", "--verbose"]);
            let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default();
            let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?;
            let complete_path: Option<String> = matches.opt_value_from_str("--complete")?;
            let goto_def_path: Option<String> = matches.opt_value_from_str("--goto-def")?;
            let op = match (highlight_path, complete_path, goto_def_path) {
                (Some(path), None, None) => analysis_bench::Op::Highlight { path: path.into() },
                (None, Some(position), None) => analysis_bench::Op::Complete(position.parse()?),
                (None, None, Some(position)) => analysis_bench::Op::GotoDef(position.parse()?),
                _ => panic!(
                    "exactly one of  `--highlight`, `--complete` or `--goto-def` must be set"
                ),
            };
            matches.finish().or_else(handle_extra_flags)?;
            analysis_bench::run(verbose, path.as_ref(), op)?;
        }
        _ => eprintln!("{}", help::GLOBAL_HELP),
    }
    Ok(())
}

fn handle_extra_flags(e: pico_args::Error) -> Result<()> {
    if let pico_args::Error::UnusedArgsLeft(flags) = e {
        let mut invalid_flags = String::new();
        for flag in flags {
            write!(&mut invalid_flags, "{}, ", flag)?;
        }
        let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2);
        Err(format!("Invalid flags: {}", invalid_flags).into())
    } else {
        Err(e.to_string().into())
    }
}

fn file() -> Result<SourceFile> {
    let text = read_stdin()?;
    Ok(SourceFile::parse(&text).tree())
}

fn read_stdin() -> Result<String> {
    let mut buff = String::new();
    std::io::stdin().read_to_string(&mut buff)?;
    Ok(buff)
}
<|endoftext|>


<commit_before>use std::ptr;
use std::os::win32::as_utf16_p;
use ll::*;

pub trait Window {
    fn hwnd(&self) -> HWND;
}

pub struct EmptyWindow {
    raw: HWND,
}

impl Window for EmptyWindow {
    fn hwnd(&self) -> HWND {
        self.raw
    }
}

pub fn null() -> EmptyWindow {
    EmptyWindow {
        raw: ptr::null(),
    }
}

pub trait WindowUtil {
    pub fn message_box(&self, msg: &str, title: &str);

    pub fn show(&self, cmd_show: int) -> bool;

    pub fn update(&self) -> bool;
}

impl<T: Window> WindowUtil for T {
    pub fn message_box(&self, msg: &str, title: &str) {
        do as_utf16_p(msg) |msg_p| {
            do as_utf16_p(title) |title_p| {
                unsafe {
                    user32::MessageBoxW(self.hwnd(), msg_p, title_p, 0u32);
                }
            }
        }
    }

    pub fn show(&self, cmd_show: int) -> bool {
        unsafe { user32::ShowWindow(self.hwnd(), cmd_show as c_int) as bool }
    }

    pub fn update(&self) -> bool {
        unsafe { user32::UpdateWindow(self.hwnd()) as bool }
    }
}
<commit_msg>Extract DialogUtil from WindowUtil<commit_after>use std::ptr;
use std::os::win32::as_utf16_p;
use ll::*;

pub trait Window {
    fn hwnd(&self) -> HWND;
}

pub struct EmptyWindow {
    raw: HWND,
}

impl Window for EmptyWindow {
    fn hwnd(&self) -> HWND {
        self.raw
    }
}

pub fn null() -> EmptyWindow {
    EmptyWindow {
        raw: ptr::null(),
    }
}

pub trait WindowUtil {
    pub fn show(&self, cmd_show: int) -> bool;

    pub fn update(&self) -> bool;
}

impl<T: Window> WindowUtil for T {
    pub fn show(&self, cmd_show: int) -> bool {
        unsafe { user32::ShowWindow(self.hwnd(), cmd_show as c_int) as bool }
    }

    pub fn update(&self) -> bool {
        unsafe { user32::UpdateWindow(self.hwnd()) as bool }
    }
}

pub trait DialogUtil {
    pub fn message_box(&self, msg: &str, title: &str);
}

impl<T: Window> DialogUtil for T {
    pub fn message_box(&self, msg: &str, title: &str) {
        do as_utf16_p(msg) |msg_p| {
            do as_utf16_p(title) |title_p| {
                unsafe {
                    user32::MessageBoxW(self.hwnd(), msg_p, title_p, 0u32);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//< Helpers that are useful for tests and doctests.
use crate::{
    arch::Arch,
    aspace::{AddressSpace, RelativeAddressSpace},
    module::{Module, Permissions, Section},
    RVA, VA,
};

/// configure a global logger at level==DEBUG.
pub fn init_logging() {
    let log_level = log::LevelFilter::Debug;
    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{} [{:5}] {} {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.level(),
                if log_level == log::LevelFilter::Trace {
                    record.target()
                } else {
                    ""
                },
                message
            ))
        })
        .level(log_level)
        .chain(std::io::stderr())
        .filter(|metadata| !metadata.target().starts_with("goblin::pe"))
        .apply()
        .expect("failed to configure logging");
}

/// this is for testing, so will panic on error.
pub fn load_shellcode(arch: Arch, buf: &[u8]) -> Module {
    let mut address_space = RelativeAddressSpace::with_capacity(buf.len() as u64);
    address_space.map.writezx(0x0, buf).unwrap();

    Module {
        arch,
        sections: vec![Section {
            name:           "shellcode".to_string(),
            permissions:    Permissions::RWX,
            physical_range: std::ops::Range {
                start: 0x0,
                end:   buf.len() as RVA,
            },
            virtual_range:  std::ops::Range {
                start: 0x0,
                end:   buf.len() as RVA,
            },
        }],
        address_space: address_space.into_absolute(0x0).unwrap(),
    }
}

/// this is for testing, so will panic on error.
pub fn load_shellcode32(buf: &[u8]) -> Module {
    load_shellcode(Arch::X32, buf)
}

/// this is for testing, so will panic on error.
pub fn load_shellcode64(buf: &[u8]) -> Module {
    load_shellcode(Arch::X64, buf)
}

/// this is for testing, so will panic on error.
pub fn read_insn(module: &Module, va: VA) -> zydis::DecodedInstruction {
    use crate::analysis::dis;

    let decoder = dis::get_disassembler(module).unwrap();
    let mut insn_buf = [0u8; 16];
    module.address_space.read_into(va, &mut insn_buf).unwrap();
    decoder.decode(&insn_buf).unwrap().unwrap()
}

pub fn emu_from_shellcode64(code: &[u8]) -> crate::emu::Emulator {
    let m = load_shellcode64(code);
    let mut emu = crate::emu::Emulator::from_module(&m);
    emu.reg.rip = m.address_space.base_address; // 0x0

    emu.mem.mmap(0x5000, 0x2000, Permissions::RW).unwrap();
    emu.reg.rsp = 0x6000;
    emu.reg.rbp = 0x6000;

    emu
}

pub fn emu_from_shellcode32(code: &[u8]) -> crate::emu::Emulator {
    let m = load_shellcode32(code);
    let mut emu = crate::emu::Emulator::from_module(&m);
    emu.reg.set_eip(m.address_space.base_address as u32); // 0x0

    emu.mem.mmap(0x5000, 0x2000, Permissions::RW).unwrap();
    emu.reg.set_esp(0x6000);
    emu.reg.set_ebp(0x6000);

    emu
}

#[cfg(test)]
pub mod uc {
    use byteorder::{ByteOrder, LittleEndian};
    use unicorn::Cpu;

    use super::load_shellcode64;
    use crate::{
        aspace::AddressSpace,
        emu::{mmu::PAGE_SIZE, reg::STATUS_MASK},
        module::{Module, Permissions},
    };

    pub struct Uc {
        emu: unicorn::CpuX86,
    }

    impl Uc {
        pub fn from_module(m: &Module) -> Uc {
            let emu = match m.arch {
                crate::arch::Arch::X32 => unicorn::CpuX86::new(unicorn::Mode::MODE_32).unwrap(),
                crate::arch::Arch::X64 => unicorn::CpuX86::new(unicorn::Mode::MODE_64).unwrap(),
            };

            for section in m.sections.iter() {
                let mut page_addr = section.virtual_range.start;

                let section_size = section.virtual_range.end - section.virtual_range.start;
                emu.mem_map(
                    section.virtual_range.start,
                    crate::util::align(section_size, PAGE_SIZE as u64) as usize,
                    unicorn::PROT_WRITE,
                )
                .unwrap();

                while page_addr < section.virtual_range.end {
                    let mut page = [0u8; PAGE_SIZE];

                    // AddressSpace currently allows non-page-aligned sizes.
                    let page_data = if page_addr + PAGE_SIZE as u64 > section.virtual_range.end {
                        &mut page[..(section.virtual_range.end - page_addr) as usize]
                    } else {
                        &mut page[..]
                    };

                    m.address_space.read_into(page_addr, page_data).unwrap();
                    emu.mem_write(page_addr, &page[..]).unwrap();
                    page_addr += PAGE_SIZE as u64;
                }

                let mut prot = unicorn::PROT_NONE;
                if section.permissions.intersects(Permissions::W) {
                    prot.insert(unicorn::PROT_WRITE);
                }
                if section.permissions.intersects(Permissions::R) {
                    prot.insert(unicorn::PROT_READ);
                }
                if section.permissions.intersects(Permissions::X) {
                    prot.insert(unicorn::PROT_EXEC);
                }

                emu.mem_protect(
                    section.virtual_range.start,
                    crate::util::align(section_size, PAGE_SIZE as u64) as usize,
                    prot,
                )
                .unwrap();
            }

            Uc { emu }
        }

        pub fn step(&mut self) -> Result<(), unicorn::Error> {
            let rip = self.emu.reg_read(unicorn::RegisterX86::RIP).unwrap();
            self.emu.emu_start(rip, u64::MAX, 0, 1)
        }

        pub fn mem_read_u64(&self, addr: u64) -> Result<u64, unicorn::Error> {
            let buf = self.emu.mem_read(addr, 8)?;
            Ok(LittleEndian::read_u64(&buf))
        }

        /// panics if the given emulator does have the same state as this.
        pub fn check(&self, other: &crate::emu::Emulator) {
            use unicorn::RegisterX86::*;

            assert_eq!(
                self.emu.reg_read(RIP).unwrap(),
                other.reg.rip(),
                "register: rip, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RIP).unwrap(),
                other.reg.rip()
            );

            assert_eq!(
                self.emu.reg_read(RSP).unwrap(),
                other.reg.rsp(),
                "register: rsp, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RSP).unwrap(),
                other.reg.rsp()
            );

            assert_eq!(
                self.emu.reg_read(RBP).unwrap(),
                other.reg.rbp(),
                "register: rbp, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RBP).unwrap(),
                other.reg.rbp()
            );

            assert_eq!(
                self.emu.reg_read(RAX).unwrap(),
                other.reg.rax(),
                "register: rax, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RAX).unwrap(),
                other.reg.rax()
            );

            assert_eq!(
                self.emu.reg_read(RBX).unwrap(),
                other.reg.rbx(),
                "register: rbx, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RBX).unwrap(),
                other.reg.rbx()
            );

            assert_eq!(
                self.emu.reg_read(RCX).unwrap(),
                other.reg.rcx(),
                "register: rcx, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RCX).unwrap(),
                other.reg.rcx()
            );

            assert_eq!(
                self.emu.reg_read(RDX).unwrap(),
                other.reg.rdx(),
                "register: rdx, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RDX).unwrap(),
                other.reg.rdx()
            );

            assert_eq!(
                self.emu.reg_read(RSI).unwrap(),
                other.reg.rsi(),
                "register: rsi, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RSI).unwrap(),
                other.reg.rsi()
            );

            assert_eq!(
                self.emu.reg_read(RDI).unwrap(),
                other.reg.rdi(),
                "register: rdi, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RDI).unwrap(),
                other.reg.rdi()
            );

            // we don't emulate all of the flags, just the status flags.
            assert_eq!(
                self.emu.reg_read(EFLAGS).unwrap() as u64 & STATUS_MASK,
                other.reg.rflags() & STATUS_MASK,
                "flags, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(EFLAGS).unwrap() as u64 & STATUS_MASK,
                other.reg.rflags() & STATUS_MASK,
            );

            // dereferece $SP and $BP
            let rsp = other.reg.rsp();
            assert_eq!(
                self.mem_read_u64(rsp).unwrap(),
                other.mem.read_u64(rsp).unwrap(),
                "*RSP, uc: {:#x} emu: {:#x}",
                self.mem_read_u64(rsp).unwrap(),
                other.mem.read_u64(rsp).unwrap(),
            );

            let rbp = other.reg.rbp();
            assert_eq!(
                self.mem_read_u64(rbp).unwrap(),
                other.mem.read_u64(rbp).unwrap(),
                "*RBP, uc: {:#x} emu: {:#x}",
                self.mem_read_u64(rbp).unwrap(),
                other.mem.read_u64(rbp).unwrap(),
            );
        }
    }

    pub fn uc_from_shellcode64(code: &[u8]) -> Uc {
        let m = load_shellcode64(code);
        let mut uc = Uc::from_module(&m);

        uc.emu
            .reg_write(unicorn::RegisterX86::RIP, m.address_space.base_address)
            .unwrap(); // 0x0

        uc.emu.mem_map(0x5000, 0x2000, unicorn::PROT_ALL).unwrap();
        uc.emu.reg_write(unicorn::RegisterX86::RSP, 0x6000).unwrap();
        uc.emu.reg_write(unicorn::RegisterX86::RBP, 0x6000).unwrap();

        uc
    }
}
<commit_msg>emu: tests: better format EFLAGS<commit_after>//< Helpers that are useful for tests and doctests.
use crate::{
    arch::Arch,
    aspace::{AddressSpace, RelativeAddressSpace},
    module::{Module, Permissions, Section},
    RVA, VA,
};

/// configure a global logger at level==DEBUG.
pub fn init_logging() {
    let log_level = log::LevelFilter::Debug;
    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{} [{:5}] {} {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.level(),
                if log_level == log::LevelFilter::Trace {
                    record.target()
                } else {
                    ""
                },
                message
            ))
        })
        .level(log_level)
        .chain(std::io::stderr())
        .filter(|metadata| !metadata.target().starts_with("goblin::pe"))
        .apply()
        .expect("failed to configure logging");
}

/// this is for testing, so will panic on error.
pub fn load_shellcode(arch: Arch, buf: &[u8]) -> Module {
    let mut address_space = RelativeAddressSpace::with_capacity(buf.len() as u64);
    address_space.map.writezx(0x0, buf).unwrap();

    Module {
        arch,
        sections: vec![Section {
            name:           "shellcode".to_string(),
            permissions:    Permissions::RWX,
            physical_range: std::ops::Range {
                start: 0x0,
                end:   buf.len() as RVA,
            },
            virtual_range:  std::ops::Range {
                start: 0x0,
                end:   buf.len() as RVA,
            },
        }],
        address_space: address_space.into_absolute(0x0).unwrap(),
    }
}

/// this is for testing, so will panic on error.
pub fn load_shellcode32(buf: &[u8]) -> Module {
    load_shellcode(Arch::X32, buf)
}

/// this is for testing, so will panic on error.
pub fn load_shellcode64(buf: &[u8]) -> Module {
    load_shellcode(Arch::X64, buf)
}

/// this is for testing, so will panic on error.
pub fn read_insn(module: &Module, va: VA) -> zydis::DecodedInstruction {
    use crate::analysis::dis;

    let decoder = dis::get_disassembler(module).unwrap();
    let mut insn_buf = [0u8; 16];
    module.address_space.read_into(va, &mut insn_buf).unwrap();
    decoder.decode(&insn_buf).unwrap().unwrap()
}

pub fn emu_from_shellcode64(code: &[u8]) -> crate::emu::Emulator {
    let m = load_shellcode64(code);
    let mut emu = crate::emu::Emulator::from_module(&m);
    emu.reg.rip = m.address_space.base_address; // 0x0

    emu.mem.mmap(0x5000, 0x2000, Permissions::RW).unwrap();
    emu.reg.rsp = 0x6000;
    emu.reg.rbp = 0x6000;

    emu
}

pub fn emu_from_shellcode32(code: &[u8]) -> crate::emu::Emulator {
    let m = load_shellcode32(code);
    let mut emu = crate::emu::Emulator::from_module(&m);
    emu.reg.set_eip(m.address_space.base_address as u32); // 0x0

    emu.mem.mmap(0x5000, 0x2000, Permissions::RW).unwrap();
    emu.reg.set_esp(0x6000);
    emu.reg.set_ebp(0x6000);

    emu
}

#[cfg(test)]
pub mod uc {
    use byteorder::{ByteOrder, LittleEndian};
    use unicorn::Cpu;

    use super::load_shellcode64;
    use crate::{
        aspace::AddressSpace,
        emu::{mmu::PAGE_SIZE, reg::STATUS_MASK},
        module::{Module, Permissions},
    };

    pub struct Uc {
        emu: unicorn::CpuX86,
    }

    impl Uc {
        pub fn from_module(m: &Module) -> Uc {
            let emu = match m.arch {
                crate::arch::Arch::X32 => unicorn::CpuX86::new(unicorn::Mode::MODE_32).unwrap(),
                crate::arch::Arch::X64 => unicorn::CpuX86::new(unicorn::Mode::MODE_64).unwrap(),
            };

            for section in m.sections.iter() {
                let mut page_addr = section.virtual_range.start;

                let section_size = section.virtual_range.end - section.virtual_range.start;
                emu.mem_map(
                    section.virtual_range.start,
                    crate::util::align(section_size, PAGE_SIZE as u64) as usize,
                    unicorn::PROT_WRITE,
                )
                .unwrap();

                while page_addr < section.virtual_range.end {
                    let mut page = [0u8; PAGE_SIZE];

                    // AddressSpace currently allows non-page-aligned sizes.
                    let page_data = if page_addr + PAGE_SIZE as u64 > section.virtual_range.end {
                        &mut page[..(section.virtual_range.end - page_addr) as usize]
                    } else {
                        &mut page[..]
                    };

                    m.address_space.read_into(page_addr, page_data).unwrap();
                    emu.mem_write(page_addr, &page[..]).unwrap();
                    page_addr += PAGE_SIZE as u64;
                }

                let mut prot = unicorn::PROT_NONE;
                if section.permissions.intersects(Permissions::W) {
                    prot.insert(unicorn::PROT_WRITE);
                }
                if section.permissions.intersects(Permissions::R) {
                    prot.insert(unicorn::PROT_READ);
                }
                if section.permissions.intersects(Permissions::X) {
                    prot.insert(unicorn::PROT_EXEC);
                }

                emu.mem_protect(
                    section.virtual_range.start,
                    crate::util::align(section_size, PAGE_SIZE as u64) as usize,
                    prot,
                )
                .unwrap();
            }

            Uc { emu }
        }

        pub fn step(&mut self) -> Result<(), unicorn::Error> {
            let rip = self.emu.reg_read(unicorn::RegisterX86::RIP).unwrap();
            self.emu.emu_start(rip, u64::MAX, 0, 1)
        }

        pub fn mem_read_u64(&self, addr: u64) -> Result<u64, unicorn::Error> {
            let buf = self.emu.mem_read(addr, 8)?;
            Ok(LittleEndian::read_u64(&buf))
        }

        /// panics if the given emulator does have the same state as this.
        pub fn check(&self, other: &crate::emu::Emulator) {
            use unicorn::RegisterX86::*;

            assert_eq!(
                self.emu.reg_read(RIP).unwrap(),
                other.reg.rip(),
                "register: rip, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RIP).unwrap(),
                other.reg.rip()
            );

            assert_eq!(
                self.emu.reg_read(RSP).unwrap(),
                other.reg.rsp(),
                "register: rsp, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RSP).unwrap(),
                other.reg.rsp()
            );

            assert_eq!(
                self.emu.reg_read(RBP).unwrap(),
                other.reg.rbp(),
                "register: rbp, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RBP).unwrap(),
                other.reg.rbp()
            );

            assert_eq!(
                self.emu.reg_read(RAX).unwrap(),
                other.reg.rax(),
                "register: rax, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RAX).unwrap(),
                other.reg.rax()
            );

            assert_eq!(
                self.emu.reg_read(RBX).unwrap(),
                other.reg.rbx(),
                "register: rbx, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RBX).unwrap(),
                other.reg.rbx()
            );

            assert_eq!(
                self.emu.reg_read(RCX).unwrap(),
                other.reg.rcx(),
                "register: rcx, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RCX).unwrap(),
                other.reg.rcx()
            );

            assert_eq!(
                self.emu.reg_read(RDX).unwrap(),
                other.reg.rdx(),
                "register: rdx, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RDX).unwrap(),
                other.reg.rdx()
            );

            assert_eq!(
                self.emu.reg_read(RSI).unwrap(),
                other.reg.rsi(),
                "register: rsi, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RSI).unwrap(),
                other.reg.rsi()
            );

            assert_eq!(
                self.emu.reg_read(RDI).unwrap(),
                other.reg.rdi(),
                "register: rdi, uc: {:#x} emu: {:#x}",
                self.emu.reg_read(RDI).unwrap(),
                other.reg.rdi()
            );

            // we don't emulate all of the flags, just the status flags.
            assert_eq!(
                self.emu.reg_read(EFLAGS).unwrap() as u64 & STATUS_MASK,
                other.reg.rflags() & STATUS_MASK,
                "flags, uc: {:#b} emu: {:#b}",
                self.emu.reg_read(EFLAGS).unwrap() as u64 & STATUS_MASK,
                other.reg.rflags() & STATUS_MASK,
            );

            // dereferece $SP and $BP
            let rsp = other.reg.rsp();
            assert_eq!(
                self.mem_read_u64(rsp).unwrap(),
                other.mem.read_u64(rsp).unwrap(),
                "*RSP, uc: {:#x} emu: {:#x}",
                self.mem_read_u64(rsp).unwrap(),
                other.mem.read_u64(rsp).unwrap(),
            );

            let rbp = other.reg.rbp();
            assert_eq!(
                self.mem_read_u64(rbp).unwrap(),
                other.mem.read_u64(rbp).unwrap(),
                "*RBP, uc: {:#x} emu: {:#x}",
                self.mem_read_u64(rbp).unwrap(),
                other.mem.read_u64(rbp).unwrap(),
            );
        }
    }

    pub fn uc_from_shellcode64(code: &[u8]) -> Uc {
        let m = load_shellcode64(code);
        let mut uc = Uc::from_module(&m);

        uc.emu
            .reg_write(unicorn::RegisterX86::RIP, m.address_space.base_address)
            .unwrap(); // 0x0

        uc.emu.mem_map(0x5000, 0x2000, unicorn::PROT_ALL).unwrap();
        uc.emu.reg_write(unicorn::RegisterX86::RSP, 0x6000).unwrap();
        uc.emu.reg_write(unicorn::RegisterX86::RBP, 0x6000).unwrap();

        uc
    }
}
<|endoftext|>