<commit_before>use lex::{Lexeme, LexemeF, Lexer, Position};
use syntax::{Expr, ExprF};
use typed_arena::Arena;

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Error(Position, ErrorF);

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum ErrorF {
  UnexpectedEOF,
  ExpectedExpr,
  Lexer,
}

pub fn expr<'a, 'b>(
  arena: &'b mut Arena<Expr<'a, 'b, Position>>,
  lexer: &mut Lexer<'a>,
) -> Result<&'b Expr<'a, 'b, Position>, Error> {
  match lexer.next() {
    None => Err(Error(lexer.next_position(), ErrorF::UnexpectedEOF)),
    Some(Err(position)) => Err(Error(position, ErrorF::Lexer)),
    Some(Ok(Lexeme(position, lexeme))) =>
      match lexeme {
        LexemeF::Identifier(name) => {
          let expr = Expr(position, ExprF::Var(name));
          Ok(arena.alloc(expr))
        },
        _ => Err(Error(position, ErrorF::ExpectedExpr)),
      },
  }
}

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

  #[test]
  fn test_expr() {
    let mut arena = Arena::new();
    assert_eq!(
      expr(&mut arena, &mut Lexer::new("foo")),
      Ok(&Expr(Position::new(0, 1, 1), ExprF::Var("foo")))
    );
  }
}
<commit_msg>Parse Abs expressions<commit_after>use lex::{Lexeme, LexemeF, Lexer, Position};
use syntax::{Expr, ExprF};
use typed_arena::Arena;

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Error(Position, &'static str);

fn read_lexeme<'a>(lexer: &mut Lexer<'a>)
  -> Result<Lexeme<'a, Position>, Error> {
  match lexer.next() {
    None => Err(Error(lexer.next_position(), "unexpected EOF")),
    Some(Err(position)) => Err(Error(position, "unexpected input")),
    Some(Ok(lexeme)) => Ok(lexeme),
  }
}

fn read_lexeme_if<'a, T, F>(lexer: &mut Lexer<'a>, pred: F)
  -> Result<T, Error>
  where F: FnOnce(Lexeme<'a, Position>) -> Result<T, Error> {
  let lexeme = try!(read_lexeme(lexer));
  pred(lexeme)
}

pub fn read_expr<'a, 'b>(
  arena: &'b Arena<Expr<'a, 'b, Position>>,
  lexer: &mut Lexer<'a>,
) -> Result<&'b Expr<'a, 'b, Position>, Error> {
  read_expr_1(arena, lexer)
}

pub fn read_expr_1<'a, 'b>(
  arena: &'b Arena<Expr<'a, 'b, Position>>,
  lexer: &mut Lexer<'a>,
) -> Result<&'b Expr<'a, 'b, Position>, Error> {
  read_expr_2(arena, lexer)
}

pub fn read_expr_2<'a, 'b>(
  arena: &'b Arena<Expr<'a, 'b, Position>>,
  lexer: &mut Lexer<'a>,
) -> Result<&'b Expr<'a, 'b, Position>, Error> {
  let Lexeme(position, lexeme) = try!(read_lexeme(lexer));
  match lexeme {
    LexemeF::Identifier(name) => {
      let expr = Expr(position, ExprF::Var(name));
      Ok(arena.alloc(expr))
    },
    LexemeF::Fun => {
      let name = try!(read_lexeme_if(lexer, |Lexeme(p, l)| match l {
        LexemeF::Identifier(name) => Ok(name),
        _ => Err(Error(p, "expected lambda parameter")),
      }));

      try!(read_lexeme_if(lexer, |Lexeme(p, l)| match l {
        LexemeF::Arrow => Ok(()),
        _ => Err(Error(p, "expected `->`")),
      }));

      let body = try!(read_expr(arena, lexer));

      try!(read_lexeme_if(lexer, |Lexeme(p, l)| match l {
        LexemeF::End => Ok(()),
        _ => Err(Error(p, "expected `end`")),
      }));

      let expr = Expr(position, ExprF::Abs(name, body));
      Ok(arena.alloc(expr))
    },
    _ => Err(Error(position, "expected expression")),
  }
}

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

  #[test]
  fn test_read_var_expr() {
    let mut arena = Arena::new();
    assert_eq!(
      read_expr(&mut arena, &mut Lexer::new("foo")),
      Ok(&Expr(Position::new(0, 1, 1), ExprF::Var("foo")))
    );
  }

  #[test]
  fn test_read_abs_expr() {
    let mut arena = Arena::new();
    assert_eq!(
      read_expr(&mut arena, &mut Lexer::new("fun foo -> bar end")),
      Ok(&Expr(
        Position::new(0, 1, 1),
        ExprF::Abs(
          "foo",
          &Expr(
            Position::new(11, 1, 12),
            ExprF::Var("bar"),
          ),
        ),
      ))
    );
  }
}
<|endoftext|>


<commit_before>//! Client-side Wayland connector
//!
//! ## Overview
//!
//! This crate provides the interfaces and machinery to safely create
//! client applications for the wayland protocol. It is a rust wrapper
//! around the `libwayland-client.so` C library.
//!
//! The wayland protocol revolves around the creation of various objects
//! and the exchange of messages associated to these objects. The initial
//! object is always the `Display`, that you get at initialization of the
//! connection, exposed by this crate as `Display::connect_to_env()`.
//!
//! ## Protocol and messages handling model
//!
//! The protocol being bi-directional, you can send and receive messages.
//! Sending messages is done via methods of `Proxy<_>` objects, receiving
//! and handling them is done by providing implementations.
//!
//! ### Proxies
//!
//! Wayland protocol objects are represented in this crate by `Proxy<I>`
//! objects, where `I` is a type representing the interface of the considered
//! object. And object's interface (think "class" in an object-oriented context)
//! defines which messages it can send and receive.
//!
//! These proxies are used to send messages to the server (in the wayland context,
//! these are called "requests"). To do so, you need to import the appropriate
//! extension trait adding these methods. For example, to use a `Proxy<WlSurface>`,
//! you need to import `protocol::wl_surface::RequestsTrait` from this crate.
//! It is also possible to directly use the `Proxy::<I>::send(..)` method, but
//! this should only be done carefully: using it improperly can mess the protocol
//! state and cause protocol errors, which are fatal to the connection (the server
//! will kill you).
//!
//! There is not a 1 to 1 mapping between `Proxy<I>` instances and protocol
//! objects. Rather, you can think of `Proxy<I>` as an `Rc`-like handle to a
//! wayland object. Multiple instances of it can exist referring to the same
//! protocol object.
//!
//! Similarly, the lifetimes of the protocol objects and the `Proxy<I>` are
//! not tighly tied. As protocol objects are created and destroyed by protocol
//! messages, it can happen that an object gets destroyed while one or more
//! `Proxy<I>` still refers to it. In such case, these proxies will be disabled
//! and their `alive()` method will start to return `false`. Trying to send messages
//! with them will also fail.
//!
//! ### Implementations
//!
//! To receive and process messages from the server to you (in wayland context they are
//! called "events"), you need to provide an `Implementation` for each wayland object
//! created in the protocol session. Whenever a new protocol object is created, you will
//! receive a `NewProxy<I>` object. Providing an implementation via its `implement()` method
//! will turn it into a regular `Proxy<I>` object.
//!
//! **All objects must be implemented**, even if it is an implementation doing nothing.
//! Failure to do so (by dropping the `NewProxy<I>` for example) can cause future fatal
//! errors if the server tries to send an event to this object.
//!
//! An implementation is just a struct implementing the `Implementation<Proxy<I>, I::Event>`
//! trait, where `I` is the interface of the considered object:
//!
//! ```
//! // Example implementation for the wl_surface interface
//! use wayland_client::Proxy;
//! use wayland_client::protocol::wl_surface;
//! use wayland_client::commons::Implementation;
//!
//! struct MyImpl {
//!    // ...
//! }
//!
//! impl Implementation<Proxy<wl_surface::WlSurface>, wl_surface::Event> for MyImpl {
//!     fn receive(&mut self, msg: wl_surface::Event, proxy: Proxy<wl_surface::WlSurface>) {
//!         // process the message...
//!     }
//! }
//! # fn main() {}
//! ```
//!
//! The trait is also automatically implemented for `FnMut(I::Event, Proxy<I>)` closures,
//! so you can use them for simplicity if a full struct would be too cumbersome.
//!
//! ## Event Queues
//!
//! The wayland client machinnery provides the possibility to have one or more event queues
//! handling the processing of received messages. All wayland objects are associated to an
//! event queue, which controls when its events are dispatched.
//!
//! Events received from the server are stored in an internal buffer, and processed (by calling
//! the appropriate implementations) when the associated event queue is dispatched.
//!
//! A default event queue is created at the same time as the initial `Display`, and by default
//! whenever a wayland object is created, it inherits the queue of its parent (the object that sent
//! or receive the message that created the new object). It means that if you only plan to use the
//! default event queue, you don't need to worry about assigning objects to their queues.
//!
//! See the documentation of `EventQueue` for details about dispatching and integrating the event
//! queue into the event loop of your application. See the `Proxy::make_wrapper()` method for
//! details about assigning objects to event queues.
//!
//! ## Dynamic linking with `libwayland-client.so`
//!
//! If you need to gracefully handle the case of a system on which wayland is not installed (by
//! fallbacking to X11 for example), you can do so by activating the `dlopen` cargo feature.
//!
//! When this is done, the library will be loaded a runtime rather than directly linked. And trying
//! to create a `Display` on a system that does not have this library will return a `NoWaylandLib`
//! error.
//!
//! ## Auxiliary libraries
//!
//! Two auxiliary libraries are also available behind cargo features:
//!
//! - the `cursor` feature will try to load `libwayland-cursor.so`, a library helping with loading
//!   system themed cursor textures, to integrate your app in the system theme.
//! - the `egl` feature will try to load `libwayland-egl.so`, a library allowing the creation of
//!   OpenGL surface from wayland surfaces.
//!
//! Both of them will also be loaded at runtime if the `dlopen` feature was provided. See their
//! respective submodules for details about their use.

#![warn(missing_docs)]

#[macro_use]
extern crate bitflags;
extern crate libc;

extern crate wayland_commons;
#[cfg(feature = "native_lib")]
#[macro_use]
extern crate wayland_sys;

mod display;
mod event_queue;
mod globals;
mod proxy;

pub use display::{Display, ConnectError};
pub use event_queue::{EventQueue, QueueToken, ReadEventsGuard};
pub use globals::{GlobalError, GlobalEvent, GlobalManager};
pub use proxy::{NewProxy, Proxy};

#[cfg(feature = "cursor")]
pub mod cursor;

#[cfg(feature = "egl")]
pub mod egl;

/// Re-export of wayland-commons
///
/// Common traits and functions to work with wayland objects
pub mod commons {
    pub use wayland_commons::*;
}

#[cfg(feature = "native_lib")]
/// C-associated types
///
/// Required for plugging wayland-scanner generated protocols
/// or interfacing with C code using wayland objects.
pub mod sys {
    pub use super::generated::c_interfaces as protocol_interfaces;
    pub use wayland_sys::{client, common};
}

/// Generated interfaces for the core wayland protocol
pub mod protocol {
    #[cfg(feature = "native_lib")]
    pub use generated::c_api::*;
}

mod generated {
    #![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)]
    #![allow(non_upper_case_globals, non_snake_case, unused_imports)]
    #![allow(missing_docs)]

    #[cfg(feature = "native_lib")]
    pub mod c_interfaces {
        include!(concat!(env!("OUT_DIR"), "/wayland_c_interfaces.rs"));
    }
    #[cfg(feature = "native_lib")]
    pub mod c_api {
        pub(crate) use wayland_commons::{AnonymousObject, Interface, MessageGroup};
        pub(crate) use wayland_sys as sys;
        pub(crate) use {NewProxy, Proxy};
        include!(concat!(env!("OUT_DIR"), "/wayland_c_api.rs"));
    }
}
<commit_msg>cargo fmt<commit_after>//! Client-side Wayland connector
//!
//! ## Overview
//!
//! This crate provides the interfaces and machinery to safely create
//! client applications for the wayland protocol. It is a rust wrapper
//! around the `libwayland-client.so` C library.
//!
//! The wayland protocol revolves around the creation of various objects
//! and the exchange of messages associated to these objects. The initial
//! object is always the `Display`, that you get at initialization of the
//! connection, exposed by this crate as `Display::connect_to_env()`.
//!
//! ## Protocol and messages handling model
//!
//! The protocol being bi-directional, you can send and receive messages.
//! Sending messages is done via methods of `Proxy<_>` objects, receiving
//! and handling them is done by providing implementations.
//!
//! ### Proxies
//!
//! Wayland protocol objects are represented in this crate by `Proxy<I>`
//! objects, where `I` is a type representing the interface of the considered
//! object. And object's interface (think "class" in an object-oriented context)
//! defines which messages it can send and receive.
//!
//! These proxies are used to send messages to the server (in the wayland context,
//! these are called "requests"). To do so, you need to import the appropriate
//! extension trait adding these methods. For example, to use a `Proxy<WlSurface>`,
//! you need to import `protocol::wl_surface::RequestsTrait` from this crate.
//! It is also possible to directly use the `Proxy::<I>::send(..)` method, but
//! this should only be done carefully: using it improperly can mess the protocol
//! state and cause protocol errors, which are fatal to the connection (the server
//! will kill you).
//!
//! There is not a 1 to 1 mapping between `Proxy<I>` instances and protocol
//! objects. Rather, you can think of `Proxy<I>` as an `Rc`-like handle to a
//! wayland object. Multiple instances of it can exist referring to the same
//! protocol object.
//!
//! Similarly, the lifetimes of the protocol objects and the `Proxy<I>` are
//! not tighly tied. As protocol objects are created and destroyed by protocol
//! messages, it can happen that an object gets destroyed while one or more
//! `Proxy<I>` still refers to it. In such case, these proxies will be disabled
//! and their `alive()` method will start to return `false`. Trying to send messages
//! with them will also fail.
//!
//! ### Implementations
//!
//! To receive and process messages from the server to you (in wayland context they are
//! called "events"), you need to provide an `Implementation` for each wayland object
//! created in the protocol session. Whenever a new protocol object is created, you will
//! receive a `NewProxy<I>` object. Providing an implementation via its `implement()` method
//! will turn it into a regular `Proxy<I>` object.
//!
//! **All objects must be implemented**, even if it is an implementation doing nothing.
//! Failure to do so (by dropping the `NewProxy<I>` for example) can cause future fatal
//! errors if the server tries to send an event to this object.
//!
//! An implementation is just a struct implementing the `Implementation<Proxy<I>, I::Event>`
//! trait, where `I` is the interface of the considered object:
//!
//! ```
//! // Example implementation for the wl_surface interface
//! use wayland_client::Proxy;
//! use wayland_client::protocol::wl_surface;
//! use wayland_client::commons::Implementation;
//!
//! struct MyImpl {
//!    // ...
//! }
//!
//! impl Implementation<Proxy<wl_surface::WlSurface>, wl_surface::Event> for MyImpl {
//!     fn receive(&mut self, msg: wl_surface::Event, proxy: Proxy<wl_surface::WlSurface>) {
//!         // process the message...
//!     }
//! }
//! # fn main() {}
//! ```
//!
//! The trait is also automatically implemented for `FnMut(I::Event, Proxy<I>)` closures,
//! so you can use them for simplicity if a full struct would be too cumbersome.
//!
//! ## Event Queues
//!
//! The wayland client machinnery provides the possibility to have one or more event queues
//! handling the processing of received messages. All wayland objects are associated to an
//! event queue, which controls when its events are dispatched.
//!
//! Events received from the server are stored in an internal buffer, and processed (by calling
//! the appropriate implementations) when the associated event queue is dispatched.
//!
//! A default event queue is created at the same time as the initial `Display`, and by default
//! whenever a wayland object is created, it inherits the queue of its parent (the object that sent
//! or receive the message that created the new object). It means that if you only plan to use the
//! default event queue, you don't need to worry about assigning objects to their queues.
//!
//! See the documentation of `EventQueue` for details about dispatching and integrating the event
//! queue into the event loop of your application. See the `Proxy::make_wrapper()` method for
//! details about assigning objects to event queues.
//!
//! ## Dynamic linking with `libwayland-client.so`
//!
//! If you need to gracefully handle the case of a system on which wayland is not installed (by
//! fallbacking to X11 for example), you can do so by activating the `dlopen` cargo feature.
//!
//! When this is done, the library will be loaded a runtime rather than directly linked. And trying
//! to create a `Display` on a system that does not have this library will return a `NoWaylandLib`
//! error.
//!
//! ## Auxiliary libraries
//!
//! Two auxiliary libraries are also available behind cargo features:
//!
//! - the `cursor` feature will try to load `libwayland-cursor.so`, a library helping with loading
//!   system themed cursor textures, to integrate your app in the system theme.
//! - the `egl` feature will try to load `libwayland-egl.so`, a library allowing the creation of
//!   OpenGL surface from wayland surfaces.
//!
//! Both of them will also be loaded at runtime if the `dlopen` feature was provided. See their
//! respective submodules for details about their use.

#![warn(missing_docs)]

#[macro_use]
extern crate bitflags;
extern crate libc;

extern crate wayland_commons;
#[cfg(feature = "native_lib")]
#[macro_use]
extern crate wayland_sys;

mod display;
mod event_queue;
mod globals;
mod proxy;

pub use display::{ConnectError, Display};
pub use event_queue::{EventQueue, QueueToken, ReadEventsGuard};
pub use globals::{GlobalError, GlobalEvent, GlobalManager};
pub use proxy::{NewProxy, Proxy};

#[cfg(feature = "cursor")]
pub mod cursor;

#[cfg(feature = "egl")]
pub mod egl;

/// Re-export of wayland-commons
///
/// Common traits and functions to work with wayland objects
pub mod commons {
    pub use wayland_commons::*;
}

#[cfg(feature = "native_lib")]
/// C-associated types
///
/// Required for plugging wayland-scanner generated protocols
/// or interfacing with C code using wayland objects.
pub mod sys {
    pub use super::generated::c_interfaces as protocol_interfaces;
    pub use wayland_sys::{client, common};
}

/// Generated interfaces for the core wayland protocol
pub mod protocol {
    #[cfg(feature = "native_lib")]
    pub use generated::c_api::*;
}

mod generated {
    #![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)]
    #![allow(non_upper_case_globals, non_snake_case, unused_imports)]
    #![allow(missing_docs)]

    #[cfg(feature = "native_lib")]
    pub mod c_interfaces {
        include!(concat!(env!("OUT_DIR"), "/wayland_c_interfaces.rs"));
    }
    #[cfg(feature = "native_lib")]
    pub mod c_api {
        pub(crate) use wayland_commons::{AnonymousObject, Interface, MessageGroup};
        pub(crate) use wayland_sys as sys;
        pub(crate) use {NewProxy, Proxy};
        include!(concat!(env!("OUT_DIR"), "/wayland_c_api.rs"));
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate wayland_sys;
extern crate libc;

pub use generated::client as protocol;

use wayland_sys::client::wl_proxy;
use wayland_sys::common::{wl_interface, wl_argument};

mod display;
mod event_queue;

pub use event_queue::{EventQueue, EventQueueHandle, StateGuard};
pub use display::{default_connect, ConnectError};

/// Common routines for wayland proxy objects.
///
/// All wayland objects automatically implement this trait
/// as generated by the scanner.
///
/// It is mostly used for internal use by the library, and you
/// should only need these methods for interfacing with C library
/// working on wayland objects.
pub trait Proxy {
    /// Pointer to the underlying wayland proxy object
    fn ptr(&self) -> *mut wl_proxy;
    /// Create an instance from point a wayland pointer
    ///
    /// The pointer must refer to a valid wayland proxy
    /// of the appropriate interface.
    unsafe fn from_ptr(*mut wl_proxy) -> Self;
    /// Pointer to the interface representation
    fn interface_ptr() -> *const wl_interface;
    /// Internal wayland name of this interface
    fn interface_name() -> &'static str;
    /// Max version of this interface supported
    fn supported_version() -> u32;
    /// Current version of the interface this proxy is instanciated with
    fn version(&self) -> u32;
}

/// Generic handler trait
///
/// This trait is automatically implemented for objects that implement
/// the appropriate interface-specific `Handler` traits. It represents
/// the hability for a type to handle events directed to a given wayland
/// interface.
///
/// For example, implementing `wl_surface::Handler` for you type will
/// automatically provide it with an implementation of
/// `Handler<WlSurface>` as well. This is the only correct way
/// to implement this trait, and you should not attempt to implement it
/// yourself.
pub unsafe trait Handler<T: Proxy> {
    unsafe fn message(&mut self, evq: &mut EventQueueHandle, proxy: &T, opcode: u32, args: *const wl_argument) -> Result<(),()>;
}

mod generated {
    #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)]
    #![allow(non_upper_case_globals,non_snake_case,unused_imports)]

    pub mod interfaces {
        include!(concat!(env!("OUT_DIR"), "/wayland_interfaces.rs"));
    }

    pub mod client {
        // Imports that need to be available to submodules
        // but should not be in public API.
        // Will be fixable with pub(restricted).
        #[doc(hidden)] pub use {Proxy, Handler};
        #[doc(hidden)] pub use event_queue::EventQueueHandle;
        #[doc(hidden)] pub use super::interfaces;
        include!(concat!(env!("OUT_DIR"), "/wayland_api.rs"));
    }
}

pub mod sys {
    pub use wayland_sys::common::*;
    pub use wayland_sys::client::*;
}
<commit_msg>Add a disclaimer on the wayland_client docs.<commit_after>//! This doc was generate for the upcoming v0.7 of the wayland-client crate.
//! This new version is a complete change of the API. If you are looking for the
//! documentation of the crate currently on crates.io, check
//! [on docs.rs](https://docs.rs/wayland-client/0.6.2/wayland_client/).

#[macro_use] extern crate wayland_sys;
extern crate libc;

pub use generated::client as protocol;

use wayland_sys::client::wl_proxy;
use wayland_sys::common::{wl_interface, wl_argument};

mod display;
mod event_queue;

pub use event_queue::{EventQueue, EventQueueHandle, StateGuard};
pub use display::{default_connect, ConnectError};

/// Common routines for wayland proxy objects.
///
/// All wayland objects automatically implement this trait
/// as generated by the scanner.
///
/// It is mostly used for internal use by the library, and you
/// should only need these methods for interfacing with C library
/// working on wayland objects.
pub trait Proxy {
    /// Pointer to the underlying wayland proxy object
    fn ptr(&self) -> *mut wl_proxy;
    /// Create an instance from point a wayland pointer
    ///
    /// The pointer must refer to a valid wayland proxy
    /// of the appropriate interface.
    unsafe fn from_ptr(*mut wl_proxy) -> Self;
    /// Pointer to the interface representation
    fn interface_ptr() -> *const wl_interface;
    /// Internal wayland name of this interface
    fn interface_name() -> &'static str;
    /// Max version of this interface supported
    fn supported_version() -> u32;
    /// Current version of the interface this proxy is instanciated with
    fn version(&self) -> u32;
}

/// Generic handler trait
///
/// This trait is automatically implemented for objects that implement
/// the appropriate interface-specific `Handler` traits. It represents
/// the hability for a type to handle events directed to a given wayland
/// interface.
///
/// For example, implementing `wl_surface::Handler` for you type will
/// automatically provide it with an implementation of
/// `Handler<WlSurface>` as well. This is the only correct way
/// to implement this trait, and you should not attempt to implement it
/// yourself.
pub unsafe trait Handler<T: Proxy> {
    unsafe fn message(&mut self, evq: &mut EventQueueHandle, proxy: &T, opcode: u32, args: *const wl_argument) -> Result<(),()>;
}

mod generated {
    #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)]
    #![allow(non_upper_case_globals,non_snake_case,unused_imports)]

    pub mod interfaces {
        include!(concat!(env!("OUT_DIR"), "/wayland_interfaces.rs"));
    }

    pub mod client {
        // Imports that need to be available to submodules
        // but should not be in public API.
        // Will be fixable with pub(restricted).
        #[doc(hidden)] pub use {Proxy, Handler};
        #[doc(hidden)] pub use event_queue::EventQueueHandle;
        #[doc(hidden)] pub use super::interfaces;
        include!(concat!(env!("OUT_DIR"), "/wayland_api.rs"));
    }
}

pub mod sys {
    pub use wayland_sys::common::*;
    pub use wayland_sys::client::*;
}
<|endoftext|>


<commit_before>/*!
The representation of CSS property values

Enums are named after the property. Variants have the same name + the
name of the value used in the spec. This leads to some verbose names,
e.g.:

The property 'background-color' and the specified value called '<color>'
in the spec lead to the variant CSSBackgroundColorColor(Color).

At least it's consistent though.
*/

use cmp::Eq;
use std::net::url::Url;
use netsurfcss::stylesheet::CssStylesheet;
use units::{Length, AbsoluteSize, RelativeSize,
            BoxSizing, BoxLength, BoxPercent, BoxAuto, Px, Em};
use color::Color;

/** A partial CSS value, before inheritance has been resolved */
enum CSSValue<T> {
    Inherit,
    Specified(T),
}

enum CSSBackgroundAttachment {
    CSSBackgroundAttachmentScroll,
    CSSBackgroundAttachmentFixed
}

enum CSSBackgroundColor {
    CSSBackgroundColorColor(Color),
    CSSBackgroundColorTransparent
}

enum CSSBackgroundRepeat {
    CSSBackgroundRepeatRepeat,
    CSSBackgroundRepeatRepeatX,
    CSSBackgroundRepeatRepeatY,
    CSSBackgroundRepeatNoRepeat
}

enum CSSBackgroundImage {
    CSSBackgroundUri(Url),
    CSSBackgroundImageNone
}

enum CSSBorderColor {
    CSSBorderColorColor(Color),
    CSSBorderColorTransparent
}

enum CSSBorderStyle {
    CSSBorderStyleNone,
    CSSBorderStyleHidden,
    CSSBorderStyleDotted,
    CSSBorderStyleDashed,
    CSSBorderStyleSolid,
    CSSBorderStyleDouble,
    CSSBorderStyleGroove,
    CSSBorderStyleRidge,
    CSSBorderStyleInset,
    CSSBorderStyleOutset,
}

enum CSSBorderWidth {
    CSSBorderWidthThin,
    CSSBorderWidthMedium,
    CSSBorderWidthThick,
    CSSBorderWidthLength(Length)
}

enum CSSColor {
    CSSColorColor(Color)
}

enum CSSDirection {
    CSSDirectionLtr,
    CSSDirectionRtl
}

enum CSSDisplay {
    CSSDisplayInline,
    CSSDisplayBlock,
    CSSDisplayListItem,
    CSSDisplayInlineBlock,
    CSSDisplayTable,
    CSSDisplayInlineTable,
    CSSDisplayTableRowGroup,
    CSSDisplayTableHeaderGroup,
    CSSDisplayTableFooterGroup,
    CSSDisplayTableRow,
    CSSDisplayTableColumnGroup,
    CSSDisplayTableColumn,
    CSSDisplayTableCell,
    CSSDisplayTableCaption,
    CSSDisplayNone
}

enum CSSFloat {
    CSSFloatLeft,
    CSSFloatRight,
    CSSFloatNone
}

enum CSSFontSize {
    CSSFontSizeAbsoluteSize(AbsoluteSize),
    CSSFontSizeRelativeSize(RelativeSize),
    CSSFontSizeLength(Length),
    CSSFontSizePercentage(float)
}

enum CSSPosition {
    CSSPositionStatic,
    CSSPositionRelative,
    CSSPositionAbsolute,
    CSSPositionFixed
}

impl Length: cmp::Eq {
    pure fn eq(other: &Length) -> bool {
        match (self, *other) {
          (Em(a), Em(b)) => a == b,
          (Px(a), Px(b)) => a == b,
          (_, _) => false
        }
    }
    pure fn ne(other: &Length) -> bool {
        return !self.eq(other);
    }
}

impl BoxSizing: cmp::Eq {
    pure fn eq(other: &BoxSizing) -> bool {
        match (self, *other) {
          (BoxLength(a), BoxLength(b)) => a == b,
          (BoxPercent(a), BoxPercent(b)) => a == b,
          (BoxAuto, BoxAuto) => true,
          (_, _) => false
        }
    }
    pure fn ne(other: &BoxSizing) -> bool {
        return !self.eq(other);
    }
}

impl AbsoluteSize: cmp::Eq {
    pure fn eq(other: &AbsoluteSize) -> bool {
        self as uint == (*other) as uint
    }
    pure fn ne(other: &AbsoluteSize) -> bool {
        return !self.eq(other);
    }
}

impl RelativeSize: cmp::Eq {
    pure fn eq(other: &RelativeSize) -> bool {
        self as uint == (*other) as uint
    }
    pure fn ne(other: &RelativeSize) -> bool {
        return !self.eq(other);
    }
}

impl CSSBackgroundColor: cmp::Eq {
    pure fn eq(other: &CSSBackgroundColor) -> bool {
        match (self, *other) {
            (CSSBackgroundColorColor(a), CSSBackgroundColorColor(b)) => a == b,
            (CSSBackgroundColorTransparent, CSSBackgroundColorTransparent) => true,
            (_, _) => false
        }
    }
    pure fn ne(other: &CSSBackgroundColor) -> bool {
        return !self.eq(other);
    }
}

impl CSSColor: cmp::Eq {
    pure fn eq(other: &CSSColor) -> bool {
        match (self, *other) {
            (CSSColorColor(a), CSSColorColor(b)) => a == b
        }
    }
    pure fn ne(other: &CSSColor) -> bool {
        return !self.eq(other);
    }
}

impl CSSDisplay: cmp::Eq {
    pure fn eq(other: &CSSDisplay) -> bool {
        self as uint == (*other) as uint
    }
    pure fn ne(other: &CSSDisplay) -> bool {
        return !self.eq(other);
    }
}

impl CSSFontSize: cmp::Eq {
    pure fn eq(other: &CSSFontSize) -> bool {
        match (self, *other) {
            (CSSFontSizeAbsoluteSize(a), CSSFontSizeAbsoluteSize(b)) => a == b,
            (CSSFontSizeRelativeSize(a), CSSFontSizeRelativeSize(b)) => a == b,
            (CSSFontSizeLength(a), CSSFontSizeLength(b))   => a == b,
            (CSSFontSizePercentage(a), CSSFontSizePercentage(b))  => a == b,
            (_, _) => false
        }
    }
    pure fn ne(other: &CSSFontSize) -> bool {
        return !self.eq(other);
    }
}

impl<T: Eq Copy> CSSValue<T> : Eq {
    pure fn eq(other: &CSSValue<T>) -> bool {
        match (self, *other) {
            (Inherit, Inherit) => true,
            (Specified(a), Specified(b)) => a == b,
            _ => false
        }
    }
    pure fn ne(other: &CSSValue<T>) -> bool {
        return !self.eq(other);
    }
}

impl CSSBorderWidth: Eq {
    pure fn eq(other: &CSSBorderWidth) -> bool {
        match (self, *other) {
            (CSSBorderWidthThin, CSSBorderWidthThin) => true,
            (CSSBorderWidthMedium, CSSBorderWidthMedium) => true,
            (CSSBorderWidthThick, CSSBorderWidthThick) => true,
            (CSSBorderWidthLength(l1), CSSBorderWidthLength(l2)) => l1 == l2,
            (_, _) => false
        }
    }
    pure fn ne(other: &CSSBorderWidth) -> bool { !self.eq(other) }
}

<commit_msg>Organize values according to the spec<commit_after>/*!
The representation of CSS property values

Enums are named after the property. Variants have the same name + the
name of the value used in the spec. This leads to some verbose names,
e.g.:

The property 'background-color' and the specified value called '<color>'
in the spec lead to the variant CSSBackgroundColorColor(Color).

At least it's consistent though.
*/

use cmp::Eq;
use std::net::url::Url;
use netsurfcss::stylesheet::CssStylesheet;
use units::{Length, AbsoluteSize, RelativeSize,
            BoxSizing, BoxLength, BoxPercent, BoxAuto, Px, Em};
use color::Color;

/** A partial CSS value, before inheritance has been resolved */
enum CSSValue<T> {
    Inherit,
    Specified(T),
}

// CSS 2.1, Section 8 - Box model

enum CSSBorderWidth {
    CSSBorderWidthThin,
    CSSBorderWidthMedium,
    CSSBorderWidthThick,
    CSSBorderWidthLength(Length)
}

enum CSSBorderColor {
    CSSBorderColorColor(Color),
    CSSBorderColorTransparent
}

enum CSSBorderStyle {
    CSSBorderStyleNone,
    CSSBorderStyleHidden,
    CSSBorderStyleDotted,
    CSSBorderStyleDashed,
    CSSBorderStyleSolid,
    CSSBorderStyleDouble,
    CSSBorderStyleGroove,
    CSSBorderStyleRidge,
    CSSBorderStyleInset,
    CSSBorderStyleOutset,
}

// CSS 2.1, Section 9 - Visual formatting model

enum CSSDisplay {
    CSSDisplayInline,
    CSSDisplayBlock,
    CSSDisplayListItem,
    CSSDisplayInlineBlock,
    CSSDisplayTable,
    CSSDisplayInlineTable,
    CSSDisplayTableRowGroup,
    CSSDisplayTableHeaderGroup,
    CSSDisplayTableFooterGroup,
    CSSDisplayTableRow,
    CSSDisplayTableColumnGroup,
    CSSDisplayTableColumn,
    CSSDisplayTableCell,
    CSSDisplayTableCaption,
    CSSDisplayNone
}

enum CSSPosition {
    CSSPositionStatic,
    CSSPositionRelative,
    CSSPositionAbsolute,
    CSSPositionFixed
}

enum CSSFloat {
    CSSFloatLeft,
    CSSFloatRight,
    CSSFloatNone
}

enum CSSDirection {
    CSSDirectionLtr,
    CSSDirectionRtl
}

// CSS 2.1, Section 10 - Visual formatting model details

// CSS 2.1, Section 11 - Visual effects

// CSS 2.1, Section 12 - Generated content, automatic numbering, and lists

// CSS 2.1, Section 13 - Paged media

// CSS 2.1, Section 14 - Colors and Backgrounds

enum CSSColor {
    CSSColorColor(Color)
}

enum CSSBackgroundColor {
    CSSBackgroundColorColor(Color),
    CSSBackgroundColorTransparent
}

enum CSSBackgroundImage {
    CSSBackgroundUri(Url),
    CSSBackgroundImageNone
}

enum CSSBackgroundRepeat {
    CSSBackgroundRepeatRepeat,
    CSSBackgroundRepeatRepeatX,
    CSSBackgroundRepeatRepeatY,
    CSSBackgroundRepeatNoRepeat
}

enum CSSBackgroundAttachment {
    CSSBackgroundAttachmentScroll,
    CSSBackgroundAttachmentFixed
}

// CSS 2.1, Section 15 - Fonts

enum CSSFontSize {
    CSSFontSizeAbsoluteSize(AbsoluteSize),
    CSSFontSizeRelativeSize(RelativeSize),
    CSSFontSizeLength(Length),
    CSSFontSizePercentage(float)
}

// CSS 2.1, Section 16 - Text

// CSS 2.1, Section 17 - Tables

// CSS 2.1, Section 18 - User interface

// Implementations of Eq

impl Length: cmp::Eq {
    pure fn eq(other: &Length) -> bool {
        match (self, *other) {
          (Em(a), Em(b)) => a == b,
          (Px(a), Px(b)) => a == b,
          (_, _) => false
        }
    }
    pure fn ne(other: &Length) -> bool {
        return !self.eq(other);
    }
}

impl BoxSizing: cmp::Eq {
    pure fn eq(other: &BoxSizing) -> bool {
        match (self, *other) {
          (BoxLength(a), BoxLength(b)) => a == b,
          (BoxPercent(a), BoxPercent(b)) => a == b,
          (BoxAuto, BoxAuto) => true,
          (_, _) => false
        }
    }
    pure fn ne(other: &BoxSizing) -> bool {
        return !self.eq(other);
    }
}

impl AbsoluteSize: cmp::Eq {
    pure fn eq(other: &AbsoluteSize) -> bool {
        self as uint == (*other) as uint
    }
    pure fn ne(other: &AbsoluteSize) -> bool {
        return !self.eq(other);
    }
}

impl RelativeSize: cmp::Eq {
    pure fn eq(other: &RelativeSize) -> bool {
        self as uint == (*other) as uint
    }
    pure fn ne(other: &RelativeSize) -> bool {
        return !self.eq(other);
    }
}

impl CSSBackgroundColor: cmp::Eq {
    pure fn eq(other: &CSSBackgroundColor) -> bool {
        match (self, *other) {
            (CSSBackgroundColorColor(a), CSSBackgroundColorColor(b)) => a == b,
            (CSSBackgroundColorTransparent, CSSBackgroundColorTransparent) => true,
            (_, _) => false
        }
    }
    pure fn ne(other: &CSSBackgroundColor) -> bool {
        return !self.eq(other);
    }
}

impl CSSColor: cmp::Eq {
    pure fn eq(other: &CSSColor) -> bool {
        match (self, *other) {
            (CSSColorColor(a), CSSColorColor(b)) => a == b
        }
    }
    pure fn ne(other: &CSSColor) -> bool {
        return !self.eq(other);
    }
}

impl CSSDisplay: cmp::Eq {
    pure fn eq(other: &CSSDisplay) -> bool {
        self as uint == (*other) as uint
    }
    pure fn ne(other: &CSSDisplay) -> bool {
        return !self.eq(other);
    }
}

impl CSSFontSize: cmp::Eq {
    pure fn eq(other: &CSSFontSize) -> bool {
        match (self, *other) {
            (CSSFontSizeAbsoluteSize(a), CSSFontSizeAbsoluteSize(b)) => a == b,
            (CSSFontSizeRelativeSize(a), CSSFontSizeRelativeSize(b)) => a == b,
            (CSSFontSizeLength(a), CSSFontSizeLength(b))   => a == b,
            (CSSFontSizePercentage(a), CSSFontSizePercentage(b))  => a == b,
            (_, _) => false
        }
    }
    pure fn ne(other: &CSSFontSize) -> bool {
        return !self.eq(other);
    }
}

impl<T: Eq Copy> CSSValue<T> : Eq {
    pure fn eq(other: &CSSValue<T>) -> bool {
        match (self, *other) {
            (Inherit, Inherit) => true,
            (Specified(a), Specified(b)) => a == b,
            _ => false
        }
    }
    pure fn ne(other: &CSSValue<T>) -> bool {
        return !self.eq(other);
    }
}

impl CSSBorderWidth: Eq {
    pure fn eq(other: &CSSBorderWidth) -> bool {
        match (self, *other) {
            (CSSBorderWidthThin, CSSBorderWidthThin) => true,
            (CSSBorderWidthMedium, CSSBorderWidthMedium) => true,
            (CSSBorderWidthThick, CSSBorderWidthThick) => true,
            (CSSBorderWidthLength(l1), CSSBorderWidthLength(l2)) => l1 == l2,
            (_, _) => false
        }
    }
    pure fn ne(other: &CSSBorderWidth) -> bool { !self.eq(other) }
}

<|endoftext|>


<commit_before>
struct median_filter_t<'a> {
    window: &'a mut u8,
    input: &'a mut usize,
    hole: &'a mut i64,
    max: &'a mut i64,
}

fn median_init(f: median_filter_t){
    *f.max = 0;
    *f.hole = 0;
}

fn median_close_hole(f: median_filter_t) {

}

fn main() {
    println!("Hello, world!");
}
<commit_msg>change struct and add other functions<commit_after>
struct median_filter_t<'a> {
    window: &'a mut Vec<u8>,
    input: &'a mut Vec<u8>,
    hole: i64,
    max: i64,
}

fn median_init(f: &mut median_filter_t, w_size: usize){
    f.max = 0;
    f.hole = 0;

    *f.window = Vec::with_capacity(w_size);
    *f.input = Vec::with_capacity(w_size/2);
}

fn median_close_hole(f: &mut median_filter_t) {
    while f.hole < f.max - 1 {
        let i: usize = f.hole as usize;
        f.window[i] = f.window[i + 1];
        f.hole += 1;
    }

    if f.hole == f.max - 1 {
        f.max = f.max - 1;
    }
}

fn media_remove(f: &mut median_filter_t, v: u8) {
    median_close_hole(f);

    let mut lo: i64 = 0;
    let mut hi: i64 = f.max - 1;

    f.hole = (hi / 2) as i64;

    while lo <= hi {
        let i: usize = f.hole as usize;
        if v > f.window[i] {
            lo = f.hole + 1;
        } else if v < f.window[i] {
            hi = f.hole - 1;
        } else {
            break;
        }
        f.hole = (lo + hi) / 2;
    }
}

fn median_add(f: &mut median_filter_t, v: u8) {
    if f.hole == f.max {
        f.max += 1;
    }

    let mut i: usize = f.hole as usize;
    while (f.hole > 0) && (f.window[i] > v) {
        f.window[i] = f.window[i-1];
        f.hole -= 1;
        i = f.hole as usize;
    }

    i = f.hole as usize;

    while (f.hole < f.max - 1) && (f.window[i+1] < v) {
        f.window[i] = f.window[i+1];
        f.hole += 1;
        i = f.hole as usize;
    }

    f.window[i] = v;
    f.hole = f.max;
}

fn main() {
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>static version: uint = 1u;

// some definitions from kissdb.h

struct Kissdb {
  hash_table_size : u8,
  key_size : u8,
  value_size : u8,
  hash_table_size_bytes : u8,
  hash_tables : ~u8,
  f : std::rt::io::file::FileWriter
}

enum Error {
  ErrorIO,
  ErrorMalloc,
  InvalidParameters,
  CorruptDbFile
}

enum OpenMode {
  ReadOnly,
  ReadWrite,
  RWCreate,
  RWReplace
}

fn main()
{
}
<commit_msg>hash funciton added<commit_after>static version: uint = 1u;

// some definitions from kissdb.h

struct Kissdb {
  hash_table_size : u64,
  key_size : u64,
  value_size : u64,
  hash_table_size_bytes : u64,
  hash_tables : ~u64,
  f : std::rt::io::file::FileWriter
}

enum Error {
  ErrorIO,
  ErrorMalloc,
  InvalidParameters,
  CorruptDbFile
}

enum OpenMode {
  ReadOnly,
  ReadWrite,
  RWCreate,
  RWReplace
}

fn kissdb_hash(b :&[u8], len: u64) -> u64
{
    let mut hash : u64 = 5381;
    for i in range (0, len) {
        hash = ((hash << 5) + hash) + (b[i] as u64);
    }
    return hash
}

fn main()
{
}
<|endoftext|>


<commit_before>/*pub use api::x11::{Window, WindowProxy, MonitorId, get_available_monitors, get_primary_monitor};
pub use api::x11::{WaitEventsIterator, PollEventsIterator};*/

use std::collections::VecDeque;
use std::sync::Arc;

use ContextError;
use CreationError;
use CursorState;
use Event;
use GlAttributes;
use GlContext;
use MouseCursor;
use PixelFormat;
use PixelFormatRequirements;
use WindowAttributes;
use libc;

use api::wayland;
use api::x11;
use api::x11::XConnection;
use api::x11::XError;
use api::x11::XNotSupported;

enum Backend {
    X(Arc<XConnection>),
    Wayland,
    Error(XNotSupported),
}

lazy_static!(
    static ref BACKEND: Backend = {
        // Wayland backend is not production-ready yet so we disable it
        if wayland::is_available() {
            Backend::Wayland
        } else {
            match XConnection::new(Some(x_error_callback)) {
                Ok(x) => Backend::X(Arc::new(x)),
                Err(e) => Backend::Error(e),
            }
        }
    };
);

pub enum Window {
    #[doc(hidden)]
    X(x11::Window),
    #[doc(hidden)]
    Wayland(wayland::Window)
}

#[derive(Clone)]
pub enum WindowProxy {
    #[doc(hidden)]
    X(x11::WindowProxy),
    #[doc(hidden)]
    Wayland(wayland::WindowProxy)
}

impl WindowProxy {
    #[inline]
    pub fn wakeup_event_loop(&self) {
        match self {
            &WindowProxy::X(ref wp) => wp.wakeup_event_loop(),
            &WindowProxy::Wayland(ref wp) => wp.wakeup_event_loop()
        }
    }
}

#[derive(Clone)]
pub enum MonitorId {
    #[doc(hidden)]
    X(x11::MonitorId),
    #[doc(hidden)]
    Wayland(wayland::MonitorId),
    #[doc(hidden)]
    None,
}

#[inline]
pub fn get_available_monitors() -> VecDeque<MonitorId> {
    match *BACKEND {
        Backend::Wayland => wayland::get_available_monitors()
                                .into_iter()
                                .map(MonitorId::Wayland)
                                .collect(),
        Backend::X(ref connec) => x11::get_available_monitors(connec)
                                    .into_iter()
                                    .map(MonitorId::X)
                                    .collect(),
        Backend::Error(_) => { let mut d = VecDeque::new(); d.push_back(MonitorId::None); d},
    }
}

#[inline]
pub fn get_primary_monitor() -> MonitorId {
    match *BACKEND {
        Backend::Wayland => MonitorId::Wayland(wayland::get_primary_monitor()),
        Backend::X(ref connec) => MonitorId::X(x11::get_primary_monitor(connec)),
        Backend::Error(_) => MonitorId::None,
    }
}

impl MonitorId {
    #[inline]
    pub fn get_name(&self) -> Option<String> {
        match self {
            &MonitorId::X(ref m) => m.get_name(),
            &MonitorId::Wayland(ref m) => m.get_name(),
            &MonitorId::None => None,
        }
    }

    #[inline]
    pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
        match self {
            &MonitorId::X(ref m) => m.get_native_identifier(),
            &MonitorId::Wayland(ref m) => m.get_native_identifier(),
            &MonitorId::None => unimplemented!()        // FIXME:
        }
    }

    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        match self {
            &MonitorId::X(ref m) => m.get_dimensions(),
            &MonitorId::Wayland(ref m) => m.get_dimensions(),
            &MonitorId::None => (800, 600),     // FIXME:
        }
    }
}

pub enum PollEventsIterator<'a> {
    #[doc(hidden)]
    X(x11::PollEventsIterator<'a>),
    #[doc(hidden)]
    Wayland(wayland::PollEventsIterator<'a>)
}

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;

    #[inline]
    fn next(&mut self) -> Option<Event> {
        match self {
            &mut PollEventsIterator::X(ref mut it) => it.next(),
            &mut PollEventsIterator::Wayland(ref mut it) => it.next()
        }
    }
}

pub enum WaitEventsIterator<'a> {
    #[doc(hidden)]
    X(x11::WaitEventsIterator<'a>),
    #[doc(hidden)]
    Wayland(wayland::WaitEventsIterator<'a>)
}

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;

    #[inline]
    fn next(&mut self) -> Option<Event> {
        match self {
            &mut WaitEventsIterator::X(ref mut it) => it.next(),
            &mut WaitEventsIterator::Wayland(ref mut it) => it.next()
        }
    }
}

impl Window {
    #[inline]
    pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements,
               opengl: &GlAttributes<&Window>) -> Result<Window, CreationError>
    {
        match *BACKEND {
            Backend::Wayland => {
                let opengl = opengl.clone().map_sharing(|w| match w {
                    &Window::Wayland(ref w) => w,
                    _ => panic!()       // TODO: return an error
                });

                wayland::Window::new(window, pf_reqs, &opengl).map(Window::Wayland)
            },

            Backend::X(ref connec) => {
                let opengl = opengl.clone().map_sharing(|w| match w {
                    &Window::X(ref w) => w,
                    _ => panic!()       // TODO: return an error
                });

                x11::Window::new(connec, window, pf_reqs, &opengl).map(Window::X)
            },

            Backend::Error(ref error) => Err(CreationError::NoBackendAvailable(Box::new(error.clone())))
        }
    }

    #[inline]
    pub fn set_title(&self, title: &str) {
        match self {
            &Window::X(ref w) => w.set_title(title),
            &Window::Wayland(ref w) => w.set_title(title)
        }
    }

    #[inline]
    pub fn show(&self) {
        match self {
            &Window::X(ref w) => w.show(),
            &Window::Wayland(ref w) => w.show()
        }
    }

    #[inline]
    pub fn hide(&self) {
        match self {
            &Window::X(ref w) => w.hide(),
            &Window::Wayland(ref w) => w.hide()
        }
    }

    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        match self {
            &Window::X(ref w) => w.get_position(),
            &Window::Wayland(ref w) => w.get_position()
        }
    }

    #[inline]
    pub fn set_position(&self, x: i32, y: i32) {
        match self {
            &Window::X(ref w) => w.set_position(x, y),
            &Window::Wayland(ref w) => w.set_position(x, y)
        }
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        match self {
            &Window::X(ref w) => w.get_inner_size(),
            &Window::Wayland(ref w) => w.get_inner_size()
        }
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        match self {
            &Window::X(ref w) => w.get_outer_size(),
            &Window::Wayland(ref w) => w.get_outer_size()
        }
    }

    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) {
        match self {
            &Window::X(ref w) => w.set_inner_size(x, y),
            &Window::Wayland(ref w) => w.set_inner_size(x, y)
        }
    }

    #[inline]
    pub fn create_window_proxy(&self) -> WindowProxy {
        match self {
            &Window::X(ref w) => WindowProxy::X(w.create_window_proxy()),
            &Window::Wayland(ref w) => WindowProxy::Wayland(w.create_window_proxy())
        }
    }

    #[inline]
    pub fn poll_events(&self) -> PollEventsIterator {
        match self {
            &Window::X(ref w) => PollEventsIterator::X(w.poll_events()),
            &Window::Wayland(ref w) => PollEventsIterator::Wayland(w.poll_events())
        }
    }

    #[inline]
    pub fn wait_events(&self) -> WaitEventsIterator {
        match self {
            &Window::X(ref w) => WaitEventsIterator::X(w.wait_events()),
            &Window::Wayland(ref w) => WaitEventsIterator::Wayland(w.wait_events())
        }
    }

    #[inline]
    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        match self {
            &mut Window::X(ref mut w) => w.set_window_resize_callback(callback),
            &mut Window::Wayland(ref mut w) => w.set_window_resize_callback(callback)
        }
    }

    #[inline]
    pub fn set_cursor(&self, cursor: MouseCursor) {
        match self {
            &Window::X(ref w) => w.set_cursor(cursor),
            &Window::Wayland(ref w) => w.set_cursor(cursor)
        }
    }

    #[inline]
    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        match self {
            &Window::X(ref w) => w.set_cursor_state(state),
            &Window::Wayland(ref w) => w.set_cursor_state(state)
        }
    }

    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
       match self {
            &Window::X(ref w) => w.hidpi_factor(),
            &Window::Wayland(ref w) => w.hidpi_factor()
        }
    }

    #[inline]
    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        match self {
            &Window::X(ref w) => w.set_cursor_position(x, y),
            &Window::Wayland(ref w) => w.set_cursor_position(x, y)
        }
    }

    #[inline]
    pub fn platform_display(&self) -> *mut libc::c_void {
        match self {
            &Window::X(ref w) => w.platform_display(),
            &Window::Wayland(ref w) => w.platform_display()
        }
    }

    #[inline]
    pub fn platform_window(&self) -> *mut libc::c_void {
        match self {
            &Window::X(ref w) => w.platform_window(),
            &Window::Wayland(ref w) => w.platform_window()
        }
    }
}

impl GlContext for Window {
    #[inline]
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        match self {
            &Window::X(ref w) => w.make_current(),
            &Window::Wayland(ref w) => w.make_current()
        }
    }

    #[inline]
    fn is_current(&self) -> bool {
        match self {
            &Window::X(ref w) => w.is_current(),
            &Window::Wayland(ref w) => w.is_current()
        }
    }

    #[inline]
    fn get_proc_address(&self, addr: &str) -> *const () {
        match self {
            &Window::X(ref w) => w.get_proc_address(addr),
            &Window::Wayland(ref w) => w.get_proc_address(addr)
        }
    }

    #[inline]
    fn swap_buffers(&self) -> Result<(), ContextError> {
        match self {
            &Window::X(ref w) => w.swap_buffers(),
            &Window::Wayland(ref w) => w.swap_buffers()
        }
    }

    #[inline]
    fn get_api(&self) -> ::Api {
        match self {
            &Window::X(ref w) => w.get_api(),
            &Window::Wayland(ref w) => w.get_api()
        }
    }

    #[inline]
    fn get_pixel_format(&self) -> PixelFormat {
        match self {
            &Window::X(ref w) => w.get_pixel_format(),
            &Window::Wayland(ref w) => w.get_pixel_format()
        }
    }
}

unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent)
                                      -> libc::c_int
{
    use std::ffi::CStr;

    if let Backend::X(ref x) = *BACKEND {
        let mut buff: Vec<u8> = Vec::with_capacity(1024);
        (x.xlib.XGetErrorText)(dpy, (*event).error_code as i32, buff.as_mut_ptr() as *mut i8, buff.capacity() as i32);
        let description = CStr::from_ptr(buff.as_mut_ptr() as *const i8).to_string_lossy();

        let error = XError {
            description: description.into_owned(),
            error_code: (*event).error_code,
            request_code: (*event).request_code,
            minor_code: (*event).minor_code,
        };

        *x.latest_error.lock().unwrap() = Some(error);
    }

    0
}
<commit_msg>Replace `i8` with `libc::c_char`<commit_after>/*pub use api::x11::{Window, WindowProxy, MonitorId, get_available_monitors, get_primary_monitor};
pub use api::x11::{WaitEventsIterator, PollEventsIterator};*/

use std::collections::VecDeque;
use std::sync::Arc;

use ContextError;
use CreationError;
use CursorState;
use Event;
use GlAttributes;
use GlContext;
use MouseCursor;
use PixelFormat;
use PixelFormatRequirements;
use WindowAttributes;
use libc;

use api::wayland;
use api::x11;
use api::x11::XConnection;
use api::x11::XError;
use api::x11::XNotSupported;

enum Backend {
    X(Arc<XConnection>),
    Wayland,
    Error(XNotSupported),
}

lazy_static!(
    static ref BACKEND: Backend = {
        // Wayland backend is not production-ready yet so we disable it
        if wayland::is_available() {
            Backend::Wayland
        } else {
            match XConnection::new(Some(x_error_callback)) {
                Ok(x) => Backend::X(Arc::new(x)),
                Err(e) => Backend::Error(e),
            }
        }
    };
);

pub enum Window {
    #[doc(hidden)]
    X(x11::Window),
    #[doc(hidden)]
    Wayland(wayland::Window)
}

#[derive(Clone)]
pub enum WindowProxy {
    #[doc(hidden)]
    X(x11::WindowProxy),
    #[doc(hidden)]
    Wayland(wayland::WindowProxy)
}

impl WindowProxy {
    #[inline]
    pub fn wakeup_event_loop(&self) {
        match self {
            &WindowProxy::X(ref wp) => wp.wakeup_event_loop(),
            &WindowProxy::Wayland(ref wp) => wp.wakeup_event_loop()
        }
    }
}

#[derive(Clone)]
pub enum MonitorId {
    #[doc(hidden)]
    X(x11::MonitorId),
    #[doc(hidden)]
    Wayland(wayland::MonitorId),
    #[doc(hidden)]
    None,
}

#[inline]
pub fn get_available_monitors() -> VecDeque<MonitorId> {
    match *BACKEND {
        Backend::Wayland => wayland::get_available_monitors()
                                .into_iter()
                                .map(MonitorId::Wayland)
                                .collect(),
        Backend::X(ref connec) => x11::get_available_monitors(connec)
                                    .into_iter()
                                    .map(MonitorId::X)
                                    .collect(),
        Backend::Error(_) => { let mut d = VecDeque::new(); d.push_back(MonitorId::None); d},
    }
}

#[inline]
pub fn get_primary_monitor() -> MonitorId {
    match *BACKEND {
        Backend::Wayland => MonitorId::Wayland(wayland::get_primary_monitor()),
        Backend::X(ref connec) => MonitorId::X(x11::get_primary_monitor(connec)),
        Backend::Error(_) => MonitorId::None,
    }
}

impl MonitorId {
    #[inline]
    pub fn get_name(&self) -> Option<String> {
        match self {
            &MonitorId::X(ref m) => m.get_name(),
            &MonitorId::Wayland(ref m) => m.get_name(),
            &MonitorId::None => None,
        }
    }

    #[inline]
    pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
        match self {
            &MonitorId::X(ref m) => m.get_native_identifier(),
            &MonitorId::Wayland(ref m) => m.get_native_identifier(),
            &MonitorId::None => unimplemented!()        // FIXME:
        }
    }

    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        match self {
            &MonitorId::X(ref m) => m.get_dimensions(),
            &MonitorId::Wayland(ref m) => m.get_dimensions(),
            &MonitorId::None => (800, 600),     // FIXME:
        }
    }
}

pub enum PollEventsIterator<'a> {
    #[doc(hidden)]
    X(x11::PollEventsIterator<'a>),
    #[doc(hidden)]
    Wayland(wayland::PollEventsIterator<'a>)
}

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;

    #[inline]
    fn next(&mut self) -> Option<Event> {
        match self {
            &mut PollEventsIterator::X(ref mut it) => it.next(),
            &mut PollEventsIterator::Wayland(ref mut it) => it.next()
        }
    }
}

pub enum WaitEventsIterator<'a> {
    #[doc(hidden)]
    X(x11::WaitEventsIterator<'a>),
    #[doc(hidden)]
    Wayland(wayland::WaitEventsIterator<'a>)
}

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;

    #[inline]
    fn next(&mut self) -> Option<Event> {
        match self {
            &mut WaitEventsIterator::X(ref mut it) => it.next(),
            &mut WaitEventsIterator::Wayland(ref mut it) => it.next()
        }
    }
}

impl Window {
    #[inline]
    pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements,
               opengl: &GlAttributes<&Window>) -> Result<Window, CreationError>
    {
        match *BACKEND {
            Backend::Wayland => {
                let opengl = opengl.clone().map_sharing(|w| match w {
                    &Window::Wayland(ref w) => w,
                    _ => panic!()       // TODO: return an error
                });

                wayland::Window::new(window, pf_reqs, &opengl).map(Window::Wayland)
            },

            Backend::X(ref connec) => {
                let opengl = opengl.clone().map_sharing(|w| match w {
                    &Window::X(ref w) => w,
                    _ => panic!()       // TODO: return an error
                });

                x11::Window::new(connec, window, pf_reqs, &opengl).map(Window::X)
            },

            Backend::Error(ref error) => Err(CreationError::NoBackendAvailable(Box::new(error.clone())))
        }
    }

    #[inline]
    pub fn set_title(&self, title: &str) {
        match self {
            &Window::X(ref w) => w.set_title(title),
            &Window::Wayland(ref w) => w.set_title(title)
        }
    }

    #[inline]
    pub fn show(&self) {
        match self {
            &Window::X(ref w) => w.show(),
            &Window::Wayland(ref w) => w.show()
        }
    }

    #[inline]
    pub fn hide(&self) {
        match self {
            &Window::X(ref w) => w.hide(),
            &Window::Wayland(ref w) => w.hide()
        }
    }

    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        match self {
            &Window::X(ref w) => w.get_position(),
            &Window::Wayland(ref w) => w.get_position()
        }
    }

    #[inline]
    pub fn set_position(&self, x: i32, y: i32) {
        match self {
            &Window::X(ref w) => w.set_position(x, y),
            &Window::Wayland(ref w) => w.set_position(x, y)
        }
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        match self {
            &Window::X(ref w) => w.get_inner_size(),
            &Window::Wayland(ref w) => w.get_inner_size()
        }
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        match self {
            &Window::X(ref w) => w.get_outer_size(),
            &Window::Wayland(ref w) => w.get_outer_size()
        }
    }

    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) {
        match self {
            &Window::X(ref w) => w.set_inner_size(x, y),
            &Window::Wayland(ref w) => w.set_inner_size(x, y)
        }
    }

    #[inline]
    pub fn create_window_proxy(&self) -> WindowProxy {
        match self {
            &Window::X(ref w) => WindowProxy::X(w.create_window_proxy()),
            &Window::Wayland(ref w) => WindowProxy::Wayland(w.create_window_proxy())
        }
    }

    #[inline]
    pub fn poll_events(&self) -> PollEventsIterator {
        match self {
            &Window::X(ref w) => PollEventsIterator::X(w.poll_events()),
            &Window::Wayland(ref w) => PollEventsIterator::Wayland(w.poll_events())
        }
    }

    #[inline]
    pub fn wait_events(&self) -> WaitEventsIterator {
        match self {
            &Window::X(ref w) => WaitEventsIterator::X(w.wait_events()),
            &Window::Wayland(ref w) => WaitEventsIterator::Wayland(w.wait_events())
        }
    }

    #[inline]
    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        match self {
            &mut Window::X(ref mut w) => w.set_window_resize_callback(callback),
            &mut Window::Wayland(ref mut w) => w.set_window_resize_callback(callback)
        }
    }

    #[inline]
    pub fn set_cursor(&self, cursor: MouseCursor) {
        match self {
            &Window::X(ref w) => w.set_cursor(cursor),
            &Window::Wayland(ref w) => w.set_cursor(cursor)
        }
    }

    #[inline]
    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        match self {
            &Window::X(ref w) => w.set_cursor_state(state),
            &Window::Wayland(ref w) => w.set_cursor_state(state)
        }
    }

    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
       match self {
            &Window::X(ref w) => w.hidpi_factor(),
            &Window::Wayland(ref w) => w.hidpi_factor()
        }
    }

    #[inline]
    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        match self {
            &Window::X(ref w) => w.set_cursor_position(x, y),
            &Window::Wayland(ref w) => w.set_cursor_position(x, y)
        }
    }

    #[inline]
    pub fn platform_display(&self) -> *mut libc::c_void {
        match self {
            &Window::X(ref w) => w.platform_display(),
            &Window::Wayland(ref w) => w.platform_display()
        }
    }

    #[inline]
    pub fn platform_window(&self) -> *mut libc::c_void {
        match self {
            &Window::X(ref w) => w.platform_window(),
            &Window::Wayland(ref w) => w.platform_window()
        }
    }
}

impl GlContext for Window {
    #[inline]
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        match self {
            &Window::X(ref w) => w.make_current(),
            &Window::Wayland(ref w) => w.make_current()
        }
    }

    #[inline]
    fn is_current(&self) -> bool {
        match self {
            &Window::X(ref w) => w.is_current(),
            &Window::Wayland(ref w) => w.is_current()
        }
    }

    #[inline]
    fn get_proc_address(&self, addr: &str) -> *const () {
        match self {
            &Window::X(ref w) => w.get_proc_address(addr),
            &Window::Wayland(ref w) => w.get_proc_address(addr)
        }
    }

    #[inline]
    fn swap_buffers(&self) -> Result<(), ContextError> {
        match self {
            &Window::X(ref w) => w.swap_buffers(),
            &Window::Wayland(ref w) => w.swap_buffers()
        }
    }

    #[inline]
    fn get_api(&self) -> ::Api {
        match self {
            &Window::X(ref w) => w.get_api(),
            &Window::Wayland(ref w) => w.get_api()
        }
    }

    #[inline]
    fn get_pixel_format(&self) -> PixelFormat {
        match self {
            &Window::X(ref w) => w.get_pixel_format(),
            &Window::Wayland(ref w) => w.get_pixel_format()
        }
    }
}

unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent)
                                      -> libc::c_int
{
    use std::ffi::CStr;

    if let Backend::X(ref x) = *BACKEND {
        let mut buff: Vec<u8> = Vec::with_capacity(1024);
        (x.xlib.XGetErrorText)(dpy, (*event).error_code as i32, buff.as_mut_ptr() as *mut libc::c_char, buff.capacity() as i32);
        let description = CStr::from_ptr(buff.as_mut_ptr() as *const libc::c_char).to_string_lossy();

        let error = XError {
            description: description.into_owned(),
            error_code: (*event).error_code,
            request_code: (*event).request_code,
            minor_code: (*event).minor_code,
        };

        *x.latest_error.lock().unwrap() = Some(error);
    }

    0
}
<|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::{BorderRadius, ClipMode, HitTestItem, HitTestResult, ItemTag, PrimitiveFlags};
use api::{PipelineId, ApiHitTester, ClipId};
use api::units::*;
use crate::clip::{ClipItemKind, ClipStore, ClipNode, rounded_rectangle_contains_point};
use crate::clip::{polygon_contains_point};
use crate::prim_store::PolygonKey;
use crate::scene_builder_thread::Interners;
use crate::spatial_tree::{SpatialNodeIndex, SpatialTree, get_external_scroll_offset};
use crate::internal_types::{FastHashMap, FastHashSet, LayoutPrimitiveInfo};
use std::ops;
use std::sync::{Arc, Mutex};
use crate::util::{LayoutToWorldFastTransform, VecHelper};

pub struct SharedHitTester {
    // We don't really need a mutex here. We could do with some sort of
    // atomic-atomic-ref-counted pointer (an Arc which would let the pointer
    // be swapped atomically like an AtomicPtr).
    // In practive this shouldn't cause performance issues, though.
    hit_tester: Mutex<Arc<HitTester>>,
}

impl SharedHitTester {
    pub fn new() -> Self {
        SharedHitTester {
            hit_tester: Mutex::new(Arc::new(HitTester::empty())),
        }
    }

    pub fn get_ref(&self) -> Arc<HitTester> {
        let guard = self.hit_tester.lock().unwrap();
        Arc::clone(&*guard)
    }

    pub(crate) fn update(&self, new_hit_tester: Arc<HitTester>) {
        let mut guard = self.hit_tester.lock().unwrap();
        *guard = new_hit_tester;
    }
}

impl ApiHitTester for SharedHitTester {
    fn hit_test(&self,
        point: WorldPoint,
    ) -> HitTestResult {
        self.get_ref().hit_test(HitTest::new(point))
    }
}

/// A copy of important spatial node data to use during hit testing. This a copy of
/// data from the SpatialTree that will persist as a new frame is under construction,
/// allowing hit tests consistent with the currently rendered frame.
#[derive(MallocSizeOf)]
struct HitTestSpatialNode {
    /// The pipeline id of this node.
    pipeline_id: PipelineId,

    /// World transform for content transformed by this node.
    world_content_transform: LayoutToWorldFastTransform,

    /// World viewport transform for content transformed by this node.
    world_viewport_transform: LayoutToWorldFastTransform,

    /// The accumulated external scroll offset for this spatial node.
    external_scroll_offset: LayoutVector2D,
}

#[derive(MallocSizeOf)]
struct HitTestClipNode {
    /// A particular point must be inside all of these regions to be considered clipped in
    /// for the purposes of a hit test.
    region: HitTestRegion,
    /// The positioning node for this clip
    spatial_node_index: SpatialNodeIndex,
}

impl HitTestClipNode {
    fn new(
        node: ClipNode,
        spatial_node_index: SpatialNodeIndex,
        interners: &Interners,
    ) -> Self {
        let region = match node.item.kind {
            ClipItemKind::Rectangle { rect, mode } => {
                HitTestRegion::Rectangle(rect, mode)
            }
            ClipItemKind::RoundedRectangle { rect, radius, mode } => {
                HitTestRegion::RoundedRectangle(rect, radius, mode)
            }
            ClipItemKind::Image { rect, polygon_handle, .. } => {
                if let Some(handle) = polygon_handle {
                    // Retrieve the polygon data from the interner.
                    let polygon = &interners.polygon[handle];
                    HitTestRegion::Polygon(rect, *polygon)
                } else {
                    HitTestRegion::Rectangle(rect, ClipMode::Clip)
                }
            }
            ClipItemKind::BoxShadow { .. } => HitTestRegion::Invalid,
        };

        HitTestClipNode {
            region,
            spatial_node_index,
        }
    }
}

#[derive(Clone, MallocSizeOf)]
struct HitTestingItem {
    rect: LayoutRect,
    clip_rect: LayoutRect,
    tag: ItemTag,
    is_backface_visible: bool,
    spatial_node_index: SpatialNodeIndex,
    #[ignore_malloc_size_of = "Range"]
    clip_nodes_range: ops::Range<ClipNodeIndex>,
}

impl HitTestingItem {
    fn new(
        tag: ItemTag,
        info: &LayoutPrimitiveInfo,
        spatial_node_index: SpatialNodeIndex,
        clip_nodes_range: ops::Range<ClipNodeIndex>,
    ) -> HitTestingItem {
        HitTestingItem {
            rect: info.rect,
            clip_rect: info.clip_rect,
            tag,
            is_backface_visible: info.flags.contains(PrimitiveFlags::IS_BACKFACE_VISIBLE),
            spatial_node_index,
            clip_nodes_range,
        }
    }
}

/// Statistics about allocation sizes of current hit tester,
/// used to pre-allocate size of the next hit tester.
pub struct HitTestingSceneStats {
    pub clip_nodes_count: usize,
    pub items_count: usize,
}

impl HitTestingSceneStats {
    pub fn empty() -> Self {
        HitTestingSceneStats {
            clip_nodes_count: 0,
            items_count: 0,
        }
    }
}

#[derive(MallocSizeOf, Debug, Copy, Clone)]
pub struct ClipNodeIndex(u32);

/// Defines the immutable part of a hit tester for a given scene.
/// The hit tester is recreated each time a frame is built, since
/// it relies on the current values of the spatial tree.
/// However, the clip chain and item definitions don't change,
/// so they are created once per scene, and shared between
/// hit tester instances via Arc.
#[derive(MallocSizeOf)]
pub struct HitTestingScene {
    /// Packed array of all hit test clip nodes
    clip_nodes: Vec<HitTestClipNode>,

    /// List of hit testing primitives.
    items: Vec<HitTestingItem>,

    /// Current stack of clip ids from stacking context
    #[ignore_malloc_size_of = "ClipId"]
    clip_id_stack: Vec<ClipId>,

    /// Last cached clip id, useful for scenes with a lot
    /// of hit-test items that reference the same clip
    #[ignore_malloc_size_of = "simple"]
    cached_clip_id: Option<(ClipId, ops::Range<ClipNodeIndex>)>,

    /// Temporary buffer used to de-duplicate clip ids when creating hit
    /// test clip nodes.
    #[ignore_malloc_size_of = "ClipId"]
    seen_clips: FastHashSet<ClipId>,
}

impl HitTestingScene {
    /// Construct a new hit testing scene, pre-allocating to size
    /// provided by previous scene stats.
    pub fn new(stats: &HitTestingSceneStats) -> Self {
        HitTestingScene {
            clip_nodes: Vec::with_capacity(stats.clip_nodes_count),
            items: Vec::with_capacity(stats.items_count),
            clip_id_stack: Vec::with_capacity(8),
            cached_clip_id: None,
            seen_clips: FastHashSet::default(),
        }
    }

    /// Get stats about the current scene allocation sizes.
    pub fn get_stats(&self) -> HitTestingSceneStats {
        HitTestingSceneStats {
            clip_nodes_count: self.clip_nodes.len(),
            items_count: self.items.len(),
        }
    }

    /// Add a hit testing primitive.
    pub fn add_item(
        &mut self,
        tag: ItemTag,
        info: &LayoutPrimitiveInfo,
        spatial_node_index: SpatialNodeIndex,
        clip_id: ClipId,
        clip_store: &ClipStore,
        interners: &Interners,
    ) {
        let clip_range = match self.cached_clip_id {
            Some((cached_clip_id, ref range)) if cached_clip_id == clip_id => {
                range.clone()
            }
            Some(_) | None => {
                let start = ClipNodeIndex(self.clip_nodes.len() as u32);

                // Clear the set of which clip ids have been encountered for this item
                self.seen_clips.clear();

                // Flatten all clips from the stacking context hierarchy
                for clip_id in &self.clip_id_stack {
                    add_clips(
                        *clip_id,
                        clip_store,
                        &mut self.clip_nodes,
                        &mut self.seen_clips,
                        interners,
                    );
                }

                // Add the primitive clip
                add_clips(
                    clip_id,
                    clip_store,
                    &mut self.clip_nodes,
                    &mut self.seen_clips,
                    interners,
                );

                let end = ClipNodeIndex(self.clip_nodes.len() as u32);

                let range = ops::Range {
                    start,
                    end,
                };

                self.cached_clip_id = Some((clip_id, range.clone()));

                range
            }
        };

        let item = HitTestingItem::new(
            tag,
            info,
            spatial_node_index,
            clip_range,
        );

        self.items.push(item);
    }

    /// Push a clip onto the current stack
    pub fn push_clip(
        &mut self,
        clip_id: ClipId,
    ) {
        // Invalidate the cache since the stack may affect the produced hit test clip struct
        self.cached_clip_id = None;

        self.clip_id_stack.push(clip_id);
    }

    /// Pop a clip from the current stack
    pub fn pop_clip(
        &mut self,
    ) {
        // Invalidate the cache since the stack may affect the produced hit test clip struct
        self.cached_clip_id = None;

        self.clip_id_stack.pop().unwrap();
    }
}

#[derive(MallocSizeOf)]
enum HitTestRegion {
    Invalid,
    Rectangle(LayoutRect, ClipMode),
    RoundedRectangle(LayoutRect, BorderRadius, ClipMode),
    Polygon(LayoutRect, PolygonKey),
}

impl HitTestRegion {
    fn contains(&self, point: &LayoutPoint) -> bool {
        match *self {
            HitTestRegion::Rectangle(ref rectangle, ClipMode::Clip) =>
                rectangle.contains(*point),
            HitTestRegion::Rectangle(ref rectangle, ClipMode::ClipOut) =>
                !rectangle.contains(*point),
            HitTestRegion::RoundedRectangle(rect, radii, ClipMode::Clip) =>
                rounded_rectangle_contains_point(point, &rect, &radii),
            HitTestRegion::RoundedRectangle(rect, radii, ClipMode::ClipOut) =>
                !rounded_rectangle_contains_point(point, &rect, &radii),
            HitTestRegion::Polygon(rect, polygon) =>
                polygon_contains_point(point, &rect, &polygon),
            HitTestRegion::Invalid => true,
        }
    }
}

#[derive(MallocSizeOf)]
pub struct HitTester {
    #[ignore_malloc_size_of = "Arc"]
    scene: Arc<HitTestingScene>,
    spatial_nodes: FastHashMap<SpatialNodeIndex, HitTestSpatialNode>,
}

impl HitTester {
    pub fn empty() -> Self {
        HitTester {
            scene: Arc::new(HitTestingScene::new(&HitTestingSceneStats::empty())),
            spatial_nodes: FastHashMap::default(),
        }
    }

    pub fn new(
        scene: Arc<HitTestingScene>,
        spatial_tree: &SpatialTree,
    ) -> HitTester {
        let mut hit_tester = HitTester {
            scene,
            spatial_nodes: FastHashMap::default(),
        };
        hit_tester.read_spatial_tree(spatial_tree);
        hit_tester
    }

    fn read_spatial_tree(
        &mut self,
        spatial_tree: &SpatialTree,
    ) {
        self.spatial_nodes.clear();
        self.spatial_nodes.reserve(spatial_tree.spatial_node_count());

        spatial_tree.visit_nodes(|index, node| {
            //TODO: avoid inverting more than necessary:
            //  - if the coordinate system is non-invertible, no need to try any of these concrete transforms
            //  - if there are other places where inversion is needed, let's not repeat the step

            self.spatial_nodes.insert(index, HitTestSpatialNode {
                pipeline_id: node.pipeline_id,
                world_content_transform: spatial_tree
                    .get_world_transform(index)
                    .into_fast_transform(),
                world_viewport_transform: spatial_tree
                    .get_world_viewport_transform(index)
                    .into_fast_transform(),
                external_scroll_offset: get_external_scroll_offset(spatial_tree, index),
            });
        });
    }

    pub fn hit_test(&self, test: HitTest) -> HitTestResult {
        let mut result = HitTestResult::default();

        let mut current_spatial_node_index = SpatialNodeIndex::INVALID;
        let mut point_in_layer = None;

        // For each hit test primitive
        for item in self.scene.items.iter().rev() {
            let scroll_node = &self.spatial_nodes[&item.spatial_node_index];
            let pipeline_id = scroll_node.pipeline_id;

            // Update the cached point in layer space, if the spatial node
            // changed since last primitive.
            if item.spatial_node_index != current_spatial_node_index {
                point_in_layer = scroll_node
                    .world_content_transform
                    .inverse()
                    .and_then(|inverted| inverted.transform_point2d(test.point));
                current_spatial_node_index = item.spatial_node_index;
            }

            // Only consider hit tests on transformable layers.
            if let Some(point_in_layer) = point_in_layer {
                // If the item's rect or clip rect don't contain this point,
                // it's not a valid hit.
                if !item.rect.contains(point_in_layer) {
                    continue;
                }
                if !item.clip_rect.contains(point_in_layer) {
                    continue;
                }

                // See if any of the clips for this primitive cull out the item.
                let mut is_valid = true;
                let clip_nodes = &self.scene.clip_nodes[item.clip_nodes_range.start.0 as usize .. item.clip_nodes_range.end.0 as usize];
                for clip_node in clip_nodes {
                    let transform = self
                        .spatial_nodes[&clip_node.spatial_node_index]
                        .world_content_transform;
                    let transformed_point = match transform
                        .inverse()
                        .and_then(|inverted| inverted.transform_point2d(test.point))
                    {
                        Some(point) => point,
                        None => {
                            continue;
                        }
                    };
                    if !clip_node.region.contains(&transformed_point) {
                        is_valid = false;
                        break;
                    }
                }
                if !is_valid {
                    continue;
                }

                // Don't hit items with backface-visibility:hidden if they are facing the back.
                if !item.is_backface_visible && scroll_node.world_content_transform.is_backface_visible() {
                    continue;
                }

                result.items.push(HitTestItem {
                    pipeline: pipeline_id,
                    tag: item.tag,
                });
            }
        }

        result.items.dedup();
        result
    }
}

#[derive(MallocSizeOf)]
pub struct HitTest {
    point: WorldPoint,
}

impl HitTest {
    pub fn new(
        point: WorldPoint,
    ) -> HitTest {
        HitTest {
            point,
        }
    }
}

/// Collect clips for a given ClipId, convert and add them to the hit testing
/// scene, if not already present.
fn add_clips(
    clip_id: ClipId,
    clip_store: &ClipStore,
    clip_nodes: &mut Vec<HitTestClipNode>,
    seen_clips: &mut FastHashSet<ClipId>,
    interners: &Interners,
) {
    // If this clip-id has already been added to this hit-test item, skip it
    if seen_clips.contains(&clip_id) {
        return;
    }
    seen_clips.insert(clip_id);

    let template = &clip_store.templates[&clip_id];
    let instances = &clip_store.instances[template.clips.start as usize .. template.clips.end as usize];

    for clip in instances {
        clip_nodes.alloc().init(
            HitTestClipNode::new(
                clip.key.into(),
                clip.key.spatial_node_index,
                interners,
            )
        );
    }

    // The ClipId parenting is terminated when we reach the root ClipId
    if clip_id != template.parent {
        add_clips(
            template.parent,
            clip_store,
            clip_nodes,
            seen_clips,
            interners,
        );
    }
}
<commit_msg>Bug 1747409 - Deindent a bit the HitTester code by early-continue-ing. r=gfx-reviewers,bradwerth<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::{BorderRadius, ClipMode, HitTestItem, HitTestResult, ItemTag, PrimitiveFlags};
use api::{PipelineId, ApiHitTester, ClipId};
use api::units::*;
use crate::clip::{ClipItemKind, ClipStore, ClipNode, rounded_rectangle_contains_point};
use crate::clip::{polygon_contains_point};
use crate::prim_store::PolygonKey;
use crate::scene_builder_thread::Interners;
use crate::spatial_tree::{SpatialNodeIndex, SpatialTree, get_external_scroll_offset};
use crate::internal_types::{FastHashMap, FastHashSet, LayoutPrimitiveInfo};
use std::ops;
use std::sync::{Arc, Mutex};
use crate::util::{LayoutToWorldFastTransform, VecHelper};

pub struct SharedHitTester {
    // We don't really need a mutex here. We could do with some sort of
    // atomic-atomic-ref-counted pointer (an Arc which would let the pointer
    // be swapped atomically like an AtomicPtr).
    // In practive this shouldn't cause performance issues, though.
    hit_tester: Mutex<Arc<HitTester>>,
}

impl SharedHitTester {
    pub fn new() -> Self {
        SharedHitTester {
            hit_tester: Mutex::new(Arc::new(HitTester::empty())),
        }
    }

    pub fn get_ref(&self) -> Arc<HitTester> {
        let guard = self.hit_tester.lock().unwrap();
        Arc::clone(&*guard)
    }

    pub(crate) fn update(&self, new_hit_tester: Arc<HitTester>) {
        let mut guard = self.hit_tester.lock().unwrap();
        *guard = new_hit_tester;
    }
}

impl ApiHitTester for SharedHitTester {
    fn hit_test(&self,
        point: WorldPoint,
    ) -> HitTestResult {
        self.get_ref().hit_test(HitTest::new(point))
    }
}

/// A copy of important spatial node data to use during hit testing. This a copy of
/// data from the SpatialTree that will persist as a new frame is under construction,
/// allowing hit tests consistent with the currently rendered frame.
#[derive(MallocSizeOf)]
struct HitTestSpatialNode {
    /// The pipeline id of this node.
    pipeline_id: PipelineId,

    /// World transform for content transformed by this node.
    world_content_transform: LayoutToWorldFastTransform,

    /// World viewport transform for content transformed by this node.
    world_viewport_transform: LayoutToWorldFastTransform,

    /// The accumulated external scroll offset for this spatial node.
    external_scroll_offset: LayoutVector2D,
}

#[derive(MallocSizeOf)]
struct HitTestClipNode {
    /// A particular point must be inside all of these regions to be considered clipped in
    /// for the purposes of a hit test.
    region: HitTestRegion,
    /// The positioning node for this clip
    spatial_node_index: SpatialNodeIndex,
}

impl HitTestClipNode {
    fn new(
        node: ClipNode,
        spatial_node_index: SpatialNodeIndex,
        interners: &Interners,
    ) -> Self {
        let region = match node.item.kind {
            ClipItemKind::Rectangle { rect, mode } => {
                HitTestRegion::Rectangle(rect, mode)
            }
            ClipItemKind::RoundedRectangle { rect, radius, mode } => {
                HitTestRegion::RoundedRectangle(rect, radius, mode)
            }
            ClipItemKind::Image { rect, polygon_handle, .. } => {
                if let Some(handle) = polygon_handle {
                    // Retrieve the polygon data from the interner.
                    let polygon = &interners.polygon[handle];
                    HitTestRegion::Polygon(rect, *polygon)
                } else {
                    HitTestRegion::Rectangle(rect, ClipMode::Clip)
                }
            }
            ClipItemKind::BoxShadow { .. } => HitTestRegion::Invalid,
        };

        HitTestClipNode {
            region,
            spatial_node_index,
        }
    }
}

#[derive(Clone, MallocSizeOf)]
struct HitTestingItem {
    rect: LayoutRect,
    clip_rect: LayoutRect,
    tag: ItemTag,
    is_backface_visible: bool,
    spatial_node_index: SpatialNodeIndex,
    #[ignore_malloc_size_of = "Range"]
    clip_nodes_range: ops::Range<ClipNodeIndex>,
}

impl HitTestingItem {
    fn new(
        tag: ItemTag,
        info: &LayoutPrimitiveInfo,
        spatial_node_index: SpatialNodeIndex,
        clip_nodes_range: ops::Range<ClipNodeIndex>,
    ) -> HitTestingItem {
        HitTestingItem {
            rect: info.rect,
            clip_rect: info.clip_rect,
            tag,
            is_backface_visible: info.flags.contains(PrimitiveFlags::IS_BACKFACE_VISIBLE),
            spatial_node_index,
            clip_nodes_range,
        }
    }
}

/// Statistics about allocation sizes of current hit tester,
/// used to pre-allocate size of the next hit tester.
pub struct HitTestingSceneStats {
    pub clip_nodes_count: usize,
    pub items_count: usize,
}

impl HitTestingSceneStats {
    pub fn empty() -> Self {
        HitTestingSceneStats {
            clip_nodes_count: 0,
            items_count: 0,
        }
    }
}

#[derive(MallocSizeOf, Debug, Copy, Clone)]
pub struct ClipNodeIndex(u32);

/// Defines the immutable part of a hit tester for a given scene.
/// The hit tester is recreated each time a frame is built, since
/// it relies on the current values of the spatial tree.
/// However, the clip chain and item definitions don't change,
/// so they are created once per scene, and shared between
/// hit tester instances via Arc.
#[derive(MallocSizeOf)]
pub struct HitTestingScene {
    /// Packed array of all hit test clip nodes
    clip_nodes: Vec<HitTestClipNode>,

    /// List of hit testing primitives.
    items: Vec<HitTestingItem>,

    /// Current stack of clip ids from stacking context
    #[ignore_malloc_size_of = "ClipId"]
    clip_id_stack: Vec<ClipId>,

    /// Last cached clip id, useful for scenes with a lot
    /// of hit-test items that reference the same clip
    #[ignore_malloc_size_of = "simple"]
    cached_clip_id: Option<(ClipId, ops::Range<ClipNodeIndex>)>,

    /// Temporary buffer used to de-duplicate clip ids when creating hit
    /// test clip nodes.
    #[ignore_malloc_size_of = "ClipId"]
    seen_clips: FastHashSet<ClipId>,
}

impl HitTestingScene {
    /// Construct a new hit testing scene, pre-allocating to size
    /// provided by previous scene stats.
    pub fn new(stats: &HitTestingSceneStats) -> Self {
        HitTestingScene {
            clip_nodes: Vec::with_capacity(stats.clip_nodes_count),
            items: Vec::with_capacity(stats.items_count),
            clip_id_stack: Vec::with_capacity(8),
            cached_clip_id: None,
            seen_clips: FastHashSet::default(),
        }
    }

    /// Get stats about the current scene allocation sizes.
    pub fn get_stats(&self) -> HitTestingSceneStats {
        HitTestingSceneStats {
            clip_nodes_count: self.clip_nodes.len(),
            items_count: self.items.len(),
        }
    }

    /// Add a hit testing primitive.
    pub fn add_item(
        &mut self,
        tag: ItemTag,
        info: &LayoutPrimitiveInfo,
        spatial_node_index: SpatialNodeIndex,
        clip_id: ClipId,
        clip_store: &ClipStore,
        interners: &Interners,
    ) {
        let clip_range = match self.cached_clip_id {
            Some((cached_clip_id, ref range)) if cached_clip_id == clip_id => {
                range.clone()
            }
            Some(_) | None => {
                let start = ClipNodeIndex(self.clip_nodes.len() as u32);

                // Clear the set of which clip ids have been encountered for this item
                self.seen_clips.clear();

                // Flatten all clips from the stacking context hierarchy
                for clip_id in &self.clip_id_stack {
                    add_clips(
                        *clip_id,
                        clip_store,
                        &mut self.clip_nodes,
                        &mut self.seen_clips,
                        interners,
                    );
                }

                // Add the primitive clip
                add_clips(
                    clip_id,
                    clip_store,
                    &mut self.clip_nodes,
                    &mut self.seen_clips,
                    interners,
                );

                let end = ClipNodeIndex(self.clip_nodes.len() as u32);

                let range = ops::Range {
                    start,
                    end,
                };

                self.cached_clip_id = Some((clip_id, range.clone()));

                range
            }
        };

        let item = HitTestingItem::new(
            tag,
            info,
            spatial_node_index,
            clip_range,
        );

        self.items.push(item);
    }

    /// Push a clip onto the current stack
    pub fn push_clip(
        &mut self,
        clip_id: ClipId,
    ) {
        // Invalidate the cache since the stack may affect the produced hit test clip struct
        self.cached_clip_id = None;

        self.clip_id_stack.push(clip_id);
    }

    /// Pop a clip from the current stack
    pub fn pop_clip(
        &mut self,
    ) {
        // Invalidate the cache since the stack may affect the produced hit test clip struct
        self.cached_clip_id = None;

        self.clip_id_stack.pop().unwrap();
    }
}

#[derive(MallocSizeOf)]
enum HitTestRegion {
    Invalid,
    Rectangle(LayoutRect, ClipMode),
    RoundedRectangle(LayoutRect, BorderRadius, ClipMode),
    Polygon(LayoutRect, PolygonKey),
}

impl HitTestRegion {
    fn contains(&self, point: &LayoutPoint) -> bool {
        match *self {
            HitTestRegion::Rectangle(ref rectangle, ClipMode::Clip) =>
                rectangle.contains(*point),
            HitTestRegion::Rectangle(ref rectangle, ClipMode::ClipOut) =>
                !rectangle.contains(*point),
            HitTestRegion::RoundedRectangle(rect, radii, ClipMode::Clip) =>
                rounded_rectangle_contains_point(point, &rect, &radii),
            HitTestRegion::RoundedRectangle(rect, radii, ClipMode::ClipOut) =>
                !rounded_rectangle_contains_point(point, &rect, &radii),
            HitTestRegion::Polygon(rect, polygon) =>
                polygon_contains_point(point, &rect, &polygon),
            HitTestRegion::Invalid => true,
        }
    }
}

#[derive(MallocSizeOf)]
pub struct HitTester {
    #[ignore_malloc_size_of = "Arc"]
    scene: Arc<HitTestingScene>,
    spatial_nodes: FastHashMap<SpatialNodeIndex, HitTestSpatialNode>,
}

impl HitTester {
    pub fn empty() -> Self {
        HitTester {
            scene: Arc::new(HitTestingScene::new(&HitTestingSceneStats::empty())),
            spatial_nodes: FastHashMap::default(),
        }
    }

    pub fn new(
        scene: Arc<HitTestingScene>,
        spatial_tree: &SpatialTree,
    ) -> HitTester {
        let mut hit_tester = HitTester {
            scene,
            spatial_nodes: FastHashMap::default(),
        };
        hit_tester.read_spatial_tree(spatial_tree);
        hit_tester
    }

    fn read_spatial_tree(
        &mut self,
        spatial_tree: &SpatialTree,
    ) {
        self.spatial_nodes.clear();
        self.spatial_nodes.reserve(spatial_tree.spatial_node_count());

        spatial_tree.visit_nodes(|index, node| {
            //TODO: avoid inverting more than necessary:
            //  - if the coordinate system is non-invertible, no need to try any of these concrete transforms
            //  - if there are other places where inversion is needed, let's not repeat the step

            self.spatial_nodes.insert(index, HitTestSpatialNode {
                pipeline_id: node.pipeline_id,
                world_content_transform: spatial_tree
                    .get_world_transform(index)
                    .into_fast_transform(),
                world_viewport_transform: spatial_tree
                    .get_world_viewport_transform(index)
                    .into_fast_transform(),
                external_scroll_offset: get_external_scroll_offset(spatial_tree, index),
            });
        });
    }

    pub fn hit_test(&self, test: HitTest) -> HitTestResult {
        let mut result = HitTestResult::default();

        let mut current_spatial_node_index = SpatialNodeIndex::INVALID;
        let mut point_in_layer = None;

        // For each hit test primitive
        for item in self.scene.items.iter().rev() {
            let scroll_node = &self.spatial_nodes[&item.spatial_node_index];
            let pipeline_id = scroll_node.pipeline_id;

            // Update the cached point in layer space, if the spatial node
            // changed since last primitive.
            if item.spatial_node_index != current_spatial_node_index {
                point_in_layer = scroll_node
                    .world_content_transform
                    .inverse()
                    .and_then(|inverted| inverted.transform_point2d(test.point));
                current_spatial_node_index = item.spatial_node_index;
            }

            // Only consider hit tests on transformable layers.
            let point_in_layer = match point_in_layer {
                Some(p) => p,
                None => continue,
            };

            // If the item's rect or clip rect don't contain this point, it's
            // not a valid hit.
            if !item.rect.contains(point_in_layer) {
                continue;
            }

            if !item.clip_rect.contains(point_in_layer) {
                continue;
            }

            // See if any of the clips for this primitive cull out the item.
            let mut is_valid = true;
            let clip_nodes = &self.scene.clip_nodes[item.clip_nodes_range.start.0 as usize .. item.clip_nodes_range.end.0 as usize];
            for clip_node in clip_nodes {
                let transform = self
                    .spatial_nodes[&clip_node.spatial_node_index]
                    .world_content_transform;
                let transformed_point = match transform
                    .inverse()
                    .and_then(|inverted| inverted.transform_point2d(test.point))
                {
                    Some(point) => point,
                    None => continue,
                };
                if !clip_node.region.contains(&transformed_point) {
                    is_valid = false;
                    break;
                }
            }
            if !is_valid {
                continue;
            }

            // Don't hit items with backface-visibility:hidden if they are facing the back.
            if !item.is_backface_visible && scroll_node.world_content_transform.is_backface_visible() {
                continue;
            }

            result.items.push(HitTestItem {
                pipeline: pipeline_id,
                tag: item.tag,
            });
        }

        result.items.dedup();
        result
    }
}

#[derive(MallocSizeOf)]
pub struct HitTest {
    point: WorldPoint,
}

impl HitTest {
    pub fn new(
        point: WorldPoint,
    ) -> HitTest {
        HitTest {
            point,
        }
    }
}

/// Collect clips for a given ClipId, convert and add them to the hit testing
/// scene, if not already present.
fn add_clips(
    clip_id: ClipId,
    clip_store: &ClipStore,
    clip_nodes: &mut Vec<HitTestClipNode>,
    seen_clips: &mut FastHashSet<ClipId>,
    interners: &Interners,
) {
    // If this clip-id has already been added to this hit-test item, skip it
    if seen_clips.contains(&clip_id) {
        return;
    }
    seen_clips.insert(clip_id);

    let template = &clip_store.templates[&clip_id];
    let instances = &clip_store.instances[template.clips.start as usize .. template.clips.end as usize];

    for clip in instances {
        clip_nodes.alloc().init(
            HitTestClipNode::new(
                clip.key.into(),
                clip.key.spatial_node_index,
                interners,
            )
        );
    }

    // The ClipId parenting is terminated when we reach the root ClipId
    if clip_id != template.parent {
        add_clips(
            template.parent,
            clip_store,
            clip_nodes,
            seen_clips,
            interners,
        );
    }
}
<|endoftext|>


<commit_before>extern crate gl_generator;

use gl_generator::{Registry, Api, Profile, Fallbacks, StructGenerator};
use std::env;
use std::fs::File;
use std::path::Path;

fn main() {
    let dest = env::var("OUT_DIR").unwrap();
    let mut file = File::create(&Path::new(&dest).join("bindings.rs")).unwrap();

    Registry::new(Api::Gl, (2, 1), Profile::Core, Fallbacks::All, [])
        .write_bindings(StructGenerator, &mut file)
        .unwrap();
}
<commit_msg>add GL_ARB_framebuffer_object extension<commit_after>extern crate gl_generator;

use gl_generator::{Registry, Api, Profile, Fallbacks, StructGenerator};
use std::env;
use std::fs::File;
use std::path::Path;

fn main() {
    let dest = env::var("OUT_DIR").unwrap();
    let mut file = File::create(&Path::new(&dest).join("bindings.rs")).unwrap();

    Registry::new(
        Api::Gl,
        (2, 1),
        Profile::Core,
        Fallbacks::All,
        ["GL_ARB_framebuffer_object"],
    ).write_bindings(StructGenerator, &mut file)
        .unwrap();
}
<|endoftext|>