<commit_before>use std::os::getenv;
use std::rc::RcMut;

use simplepattern::ParameterDictionary;
use simplepattern::SimplePattern;
use simplepattern::PatternMatcher;

pub mod simplepattern;
struct HttpContext{
    request: Request,
    response: Response,
}

impl HttpContext{
    fn create() -> HttpContext{
        HttpContext{
            request: Request::populate(),
            response: Response::new()
        }
    }
}

struct Request {
    path: ~str,
    querystring: ~str
}

impl Request {
    fn populate() -> Request {
        Request{
            path: getenv("PATH_INFO").unwrap_or(~""),
            querystring: getenv("QUERY_STRING").unwrap_or(~"")
        }
    }
}

struct Response{
    contenttype: ~str,
    body: ~str
}

impl Response{
    fn new() -> Response{
        Response{contenttype: ~"text/plain", body: ~""}
    }
}

struct Route {
    matcher: ~PatternMatcher,
    handler: ~fn(&mut ControllerContext)
}

struct Router{
    routes: ~[Route],
}

impl Router{
    fn new() -> Router{
        Router{routes: ~[]}
    }
    fn add(&mut self, r: ~Route){
        self.routes.push(*r);
    }
    fn execute(&mut self, c: &mut HttpContext) {
        for route in self.routes.iter(){
            let res=route.matcher.matches(c.request.path);

            if(res.is_match){
                (route.handler)(&mut ControllerContext{http: c, router: self, route_params: res.params});
                return;
            }
        }
        default_handler(&mut ControllerContext{http: c, router: self, route_params: ParameterDictionary::new()});
    }
    fn controller<'r,T>(&'r mut self, creator: ~fn(&mut ControllerContext) -> T) -> ControllerBox<'r,T>
    {
        ControllerBox{
            router: self,
            path: ~"",
            creator: Some(creator)
        }
    }
}

struct ControllerContext<'self>
{
    http: &'self mut HttpContext,
    router: &'self Router,
    route_params: ParameterDictionary
}

trait HttpController{

}

struct ControllerBox<'self,T>{
    router: &'self mut Router,
    path: ~str,
    creator: Option<~fn(&mut ControllerContext) -> T>
}

impl<'self,T> ControllerBox<'self,T>{
    fn handles(&'self mut self, path: ~str) -> &'self mut ControllerBox<'self,T>{
        self.path=path;
        self
    }
    fn with(&'self mut self, invoker: ~fn(&mut T, &mut ControllerContext)) -> &'self mut ControllerBox<'self,T>{
        let tmp=self.creator.take();

        self.router.add(~Route{matcher: ~SimplePattern::new(self.path) as ~PatternMatcher, handler:
         |c| {
            match tmp {
                None => (),
                Some(ref t) => {
                    let mut ctrl=(*t)(c);
                    invoker(&mut ctrl, c);
                }
            };
        }});
        self
    }
}
/*
struct Meh{
    biz: ~fn(int) -> int
}

impl Meh{
    fn foo(@mut self
}
*/

struct TestController;

impl TestController{
    fn new() -> TestController{
    TestController
    }
    fn index(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str("test index");
    }
    fn say(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str(context.route_params[~"message"]);
    }
}

fn default_handler(context: &mut ControllerContext){
    context.http.response.body.push_str("404 not found");
}

fn main() {
    let mut context=HttpContext::create();
    let mut router=Router::new();
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/test").with(|c,ctx| c.index(ctx));
    }
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/say/[message]").with(|c,ctx| c.say(ctx));
    }

    router.execute(&mut context); //possible borrowing more than once

    println(context.response.contenttype);
    println("");
    println(context.response.body);
}<commit_msg>remove useless comment<commit_after>use std::os::getenv;
use std::rc::RcMut;

use simplepattern::ParameterDictionary;
use simplepattern::SimplePattern;
use simplepattern::PatternMatcher;

pub mod simplepattern;
struct HttpContext{
    request: Request,
    response: Response,
}

impl HttpContext{
    fn create() -> HttpContext{
        HttpContext{
            request: Request::populate(),
            response: Response::new()
        }
    }
}

struct Request {
    path: ~str,
    querystring: ~str
}

impl Request {
    fn populate() -> Request {
        Request{
            path: getenv("PATH_INFO").unwrap_or(~""),
            querystring: getenv("QUERY_STRING").unwrap_or(~"")
        }
    }
}

struct Response{
    contenttype: ~str,
    body: ~str
}

impl Response{
    fn new() -> Response{
        Response{contenttype: ~"text/plain", body: ~""}
    }
}

struct Route {
    matcher: ~PatternMatcher,
    handler: ~fn(&mut ControllerContext)
}

struct Router{
    routes: ~[Route],
}

impl Router{
    fn new() -> Router{
        Router{routes: ~[]}
    }
    fn add(&mut self, r: ~Route){
        self.routes.push(*r);
    }
    fn execute(&mut self, c: &mut HttpContext) {
        for route in self.routes.iter(){
            let res=route.matcher.matches(c.request.path);

            if(res.is_match){
                (route.handler)(&mut ControllerContext{http: c, router: self, route_params: res.params});
                return;
            }
        }
        default_handler(&mut ControllerContext{http: c, router: self, route_params: ParameterDictionary::new()});
    }
    fn controller<'r,T>(&'r mut self, creator: ~fn(&mut ControllerContext) -> T) -> ControllerBox<'r,T>
    {
        ControllerBox{
            router: self,
            path: ~"",
            creator: Some(creator)
        }
    }
}

struct ControllerContext<'self>
{
    http: &'self mut HttpContext,
    router: &'self Router,
    route_params: ParameterDictionary
}

trait HttpController{

}

struct ControllerBox<'self,T>{
    router: &'self mut Router,
    path: ~str,
    creator: Option<~fn(&mut ControllerContext) -> T>
}

impl<'self,T> ControllerBox<'self,T>{
    fn handles(&'self mut self, path: ~str) -> &'self mut ControllerBox<'self,T>{
        self.path=path;
        self
    }
    fn with(&'self mut self, invoker: ~fn(&mut T, &mut ControllerContext)) -> &'self mut ControllerBox<'self,T>{
        let tmp=self.creator.take();

        self.router.add(~Route{matcher: ~SimplePattern::new(self.path) as ~PatternMatcher, handler:
         |c| {
            match tmp {
                None => (),
                Some(ref t) => {
                    let mut ctrl=(*t)(c);
                    invoker(&mut ctrl, c);
                }
            };
        }});
        self
    }
}
/*
struct Meh{
    biz: ~fn(int) -> int
}

impl Meh{
    fn foo(@mut self
}
*/

struct TestController;

impl TestController{
    fn new() -> TestController{
    TestController
    }
    fn index(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str("test index");
    }
    fn say(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str(context.route_params[~"message"]);
    }
}

fn default_handler(context: &mut ControllerContext){
    context.http.response.body.push_str("404 not found");
}

fn main() {
    let mut context=HttpContext::create();
    let mut router=Router::new();
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/test").with(|c,ctx| c.index(ctx));
    }
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/say/[message]").with(|c,ctx| c.say(ctx));
    }

    router.execute(&mut context);

    println(context.response.contenttype);
    println("");
    println(context.response.body);
}<|endoftext|>


<commit_before>#![allow(clippy::clone_on_ref_ptr)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::not_unsafe_ptr_arg_deref)]
#![allow(clippy::too_many_arguments)]
#![warn(unused)]

#[rustfmt::skip]
pub use crate::c_api::{
    rsvg_rust_error_get_type,
    rsvg_rust_handle_close,
    rsvg_rust_handle_flags_get_type,
    rsvg_rust_handle_get_base_url,
    rsvg_rust_handle_get_dimensions,
    rsvg_rust_handle_get_dimensions_sub,
    rsvg_rust_handle_get_geometry_for_element,
    rsvg_rust_handle_get_geometry_for_layer,
    rsvg_rust_handle_get_intrinsic_dimensions,
    rsvg_rust_handle_get_pixbuf_sub,
    rsvg_rust_handle_get_position_sub,
    rsvg_rust_handle_has_sub,
    rsvg_rust_handle_new_from_data,
    rsvg_rust_handle_new_from_file,
    rsvg_rust_handle_new_from_gfile_sync,
    rsvg_rust_handle_new_from_stream_sync,
    rsvg_rust_handle_new_with_flags,
    rsvg_rust_handle_read_stream_sync,
    rsvg_rust_handle_render_cairo_sub,
    rsvg_rust_handle_render_element,
    rsvg_rust_handle_render_document,
    rsvg_rust_handle_render_layer,
    rsvg_rust_handle_set_base_gfile,
    rsvg_rust_handle_set_base_url,
    rsvg_rust_handle_set_dpi_x_y,
    rsvg_rust_handle_set_size_callback,
    rsvg_rust_handle_set_testing,
    rsvg_rust_handle_write,
};

pub use crate::color_utils::rsvg_css_parse_color;

pub use crate::dpi::rsvg_rust_set_default_dpi_x_y;

#[rustfmt::skip]
pub use crate::pixbuf_utils::{
    rsvg_rust_pixbuf_from_file_at_max_size,
    rsvg_rust_pixbuf_from_file_at_size,
    rsvg_rust_pixbuf_from_file_at_zoom,
    rsvg_rust_pixbuf_from_file_at_zoom_with_max,
};

#[macro_use]
mod messages;

mod c_api;
mod color_utils;
mod dpi;
pub mod pixbuf_utils;
<commit_msg>Remove unnecessary clippy configurations<commit_after>#![allow(clippy::missing_safety_doc)]
#![warn(unused)]

#[rustfmt::skip]
pub use crate::c_api::{
    rsvg_rust_error_get_type,
    rsvg_rust_handle_close,
    rsvg_rust_handle_flags_get_type,
    rsvg_rust_handle_get_base_url,
    rsvg_rust_handle_get_dimensions,
    rsvg_rust_handle_get_dimensions_sub,
    rsvg_rust_handle_get_geometry_for_element,
    rsvg_rust_handle_get_geometry_for_layer,
    rsvg_rust_handle_get_intrinsic_dimensions,
    rsvg_rust_handle_get_pixbuf_sub,
    rsvg_rust_handle_get_position_sub,
    rsvg_rust_handle_has_sub,
    rsvg_rust_handle_new_from_data,
    rsvg_rust_handle_new_from_file,
    rsvg_rust_handle_new_from_gfile_sync,
    rsvg_rust_handle_new_from_stream_sync,
    rsvg_rust_handle_new_with_flags,
    rsvg_rust_handle_read_stream_sync,
    rsvg_rust_handle_render_cairo_sub,
    rsvg_rust_handle_render_element,
    rsvg_rust_handle_render_document,
    rsvg_rust_handle_render_layer,
    rsvg_rust_handle_set_base_gfile,
    rsvg_rust_handle_set_base_url,
    rsvg_rust_handle_set_dpi_x_y,
    rsvg_rust_handle_set_size_callback,
    rsvg_rust_handle_set_testing,
    rsvg_rust_handle_write,
};

pub use crate::color_utils::rsvg_css_parse_color;

pub use crate::dpi::rsvg_rust_set_default_dpi_x_y;

#[rustfmt::skip]
pub use crate::pixbuf_utils::{
    rsvg_rust_pixbuf_from_file_at_max_size,
    rsvg_rust_pixbuf_from_file_at_size,
    rsvg_rust_pixbuf_from_file_at_zoom,
    rsvg_rust_pixbuf_from_file_at_zoom_with_max,
};

#[macro_use]
mod messages;

mod c_api;
mod color_utils;
mod dpi;
pub mod pixbuf_utils;
<|endoftext|>


<commit_before>#![recursion_limit = "128"]

extern crate proc_macro;
use proc_macro::TokenStream;

extern crate heck;
extern crate proc_macro2;
extern crate syn;

#[macro_use]
extern crate quote;

mod context;
mod ex_struct;
mod init;
mod map;
mod nif;
mod record;
mod tuple;
mod unit_enum;
mod untagged_enum;

#[derive(Debug)]
enum RustlerAttr {
    Encode,
    Decode,
    Module(String),
    Tag(String),
}

/// Implementation of a Native Implementated Function (NIF) macro that lets the user annotate
/// a function that will be wrapped in higer-level NIF implementation.
///
/// ```ignore
/// #[rustler::nif]
/// fn add(a: i64, b: i64) -> i64 {
///     a + b
/// }
///
/// #[rustler::nif]
/// fn sub(a: i64, b: i64) -> i64 {
///     a - b
/// }
///
/// #[rustler::nif]
/// fn mul(a: i64, b: i64) -> i64 {
///     a * b
/// }
///
/// #[rustler::nif]
/// fn div(a: i64, b: i64) -> i64 {
///     a / b
/// }
///
/// rustler::init!("Elixir.Math", [add, sub, mul, div], Some(load));
/// ```
#[proc_macro]
pub fn init(input: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(input as init::InitMacroInput);
    let output: proc_macro2::TokenStream = input.into();
    output.into()
}

/// Implementation of a Native Implementated Function (NIF) macro that lets the user annotate
/// a function that will be wrapped in higer-level NIF implementation.
///
/// ```ignore
/// #[nif]
/// fn add(a: i64, b: i64) -> i64 {
///     a + b
/// }
/// ```
#[proc_macro_attribute]
pub fn nif(args: TokenStream, input: TokenStream) -> TokenStream {
    let args = syn::parse_macro_input!(args as syn::AttributeArgs);
    let input = syn::parse_macro_input!(input as syn::ItemFn);

    nif::transcoder_decorator(args, input).into()
}

/// Implementation of the `NifStruct` macro that lets the user annotate a struct that will
/// be translated directly from an Elixir struct to a Rust struct. For example, the following
/// struct, annotated as such:
///
/// ```ignore
/// #[derive(Debug, NifStruct)]
/// #[module = "AddStruct"]
/// struct AddStruct {
///    lhs: i32,
///    rhs: i32,
/// }
/// ```
///
/// This would be translated by Rustler into:
///
/// ```elixir
/// defmodule AddStruct do
///   defstruct lhs: 0, rhs: 0
/// end
/// ```
#[proc_macro_derive(NifStruct, attributes(module, rustler))]
pub fn nif_struct(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    ex_struct::transcoder_decorator(&ast, false).into()
}

#[proc_macro_derive(NifException, attributes(module, rustler))]
pub fn nif_exception(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    ex_struct::transcoder_decorator(&ast, true).into()
}

/// Implementation of a macro that lets the user annotate a struct with `NifMap` so that the
/// struct can be encoded or decoded from an Elixir map. For example, the following struct
/// annotated as such:
///
/// ```ignore
/// #[derive(NifMap)]
/// struct AddMap {
///     lhs: i32,
///     rhs: i32,
/// }
/// ```
///
/// Given the values 33 and 21 for this struct, this would result, when encoded, in an elixir
/// map with two elements like:
///
/// ```elixir
/// %{lhs: 33, rhs: 21}
/// ```
#[proc_macro_derive(NifMap, attributes(rustler))]
pub fn nif_map(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    map::transcoder_decorator(&ast).into()
}

/// Implementation of a macro that lets the user annotate a struct with `NifTuple` so that the
/// struct can be encoded or decoded from an Elixir tuple. For example, the following struct
/// annotated as such:
///
/// ```ignore
/// #[derive(NifTuple)]
/// struct AddTuple {
///     lhs: i32,
///     rhs: i32,
/// }
/// ```
///
/// Given the values 33 and 21 for this struct, this would result, when encoded, in an elixir
/// tuple with two elements like:
///
/// ```elixir
/// {33, 21}
/// ```
///
/// The size of the tuple will depend on the number of elements in the struct.
#[proc_macro_derive(NifTuple, attributes(rustler))]
pub fn nif_tuple(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    tuple::transcoder_decorator(&ast).into()
}

/// Implementation of the `NifRecord` macro that lets the user annotate a struct that will
/// be translated directly from an Elixir struct to a Rust struct. For example, the following
/// struct, annotated as such:
///
/// ```ignore
/// #[derive(Debug, NifRecord)]
/// #[tag = "record"]
/// struct AddRecord {
///    lhs: i32,
///    rhs: i32,
/// }
/// ```
///
/// This would be translated by Rustler into:
///
/// ```elixir
/// defmodule AddRecord do
///   import Record
///   defrecord :record, [lhs: 1, rhs: 2]
/// end
/// ```
#[proc_macro_derive(NifRecord, attributes(tag, rustler))]
pub fn nif_record(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    record::transcoder_decorator(&ast).into()
}

/// Implementation of the `NifUnitEnum` macro that lets the user annotate an enum with a unit type
/// that will generate elixir atoms when encoded
///
/// ```ignore
/// #[derive(NifUnitEnum)]
/// enum UnitEnum {
///    FooBar,
///    Baz,
/// }
/// ```
///
/// An example usage in elixir would look like the following.
///
/// ```elixir
/// test "unit enum transcoder" do
///   assert :foo_bar == RustlerTest.unit_enum_echo(:foo_bar)
///   assert :baz == RustlerTest.unit_enum_echo(:baz)
///   assert :invalid_variant == RustlerTest.unit_enum_echo(:somethingelse)
/// end
/// ```
///
/// Note that the `:invalid_variant` atom is returned if the user tries to encode something
/// that isn't in the Rust enum.
#[proc_macro_derive(NifUnitEnum, attributes(rustler))]
pub fn nif_unit_enum(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    unit_enum::transcoder_decorator(&ast).into()
}

/// Implementation of the `NifUntaggedEnum` macro that lets the user annotate an enum that will
/// generate elixir values when decoded. This can be used for rust enums that contain data and
/// will generate a value based on the kind of data encoded. For example from the test code:
///
/// ```ignore
/// #[derive(NifUntaggedEnum)]
/// enum UntaggedEnum {
///     Foo(u32),
///     Bar(String),
///     Baz(AddStruct),
/// }
///
/// pub fn untagged_enum_echo<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult<Term<'a>> {
///     let untagged_enum: UntaggedEnum = args[0].decode()?;
///     Ok(untagged_enum.encode(env))
/// }
/// ```
///
/// This can be used from elixir in the following manner.
///
/// ```elixir
/// test "untagged enum transcoder" do
///   assert 123 == RustlerTest.untagged_enum_echo(123)
///   assert "Hello" == RustlerTest.untagged_enum_echo("Hello")
///   assert %AddStruct{lhs: 45, rhs: 123} = RustlerTest.untagged_enum_echo(%AddStruct{lhs: 45, rhs: 123})
///   assert :invalid_variant == RustlerTest.untagged_enum_echo([1,2,3,4])
/// end
/// ```
///
/// Note that the type of elixir return is dependent on the data in the enum and the actual enum
/// type is lost in the translation because Elixir has no such concept.
#[proc_macro_derive(NifUntaggedEnum, attributes(rustler))]
pub fn nif_untagged_enum(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    untagged_enum::transcoder_decorator(&ast).into()
}
<commit_msg>Add docs for NifException macro<commit_after>#![recursion_limit = "128"]

extern crate proc_macro;
use proc_macro::TokenStream;

extern crate heck;
extern crate proc_macro2;
extern crate syn;

#[macro_use]
extern crate quote;

mod context;
mod ex_struct;
mod init;
mod map;
mod nif;
mod record;
mod tuple;
mod unit_enum;
mod untagged_enum;

#[derive(Debug)]
enum RustlerAttr {
    Encode,
    Decode,
    Module(String),
    Tag(String),
}

/// Implementation of a Native Implementated Function (NIF) macro that lets the user annotate
/// a function that will be wrapped in higer-level NIF implementation.
///
/// ```ignore
/// #[rustler::nif]
/// fn add(a: i64, b: i64) -> i64 {
///     a + b
/// }
///
/// #[rustler::nif]
/// fn sub(a: i64, b: i64) -> i64 {
///     a - b
/// }
///
/// #[rustler::nif]
/// fn mul(a: i64, b: i64) -> i64 {
///     a * b
/// }
///
/// #[rustler::nif]
/// fn div(a: i64, b: i64) -> i64 {
///     a / b
/// }
///
/// rustler::init!("Elixir.Math", [add, sub, mul, div], Some(load));
/// ```
#[proc_macro]
pub fn init(input: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(input as init::InitMacroInput);
    let output: proc_macro2::TokenStream = input.into();
    output.into()
}

/// Implementation of a Native Implementated Function (NIF) macro that lets the user annotate
/// a function that will be wrapped in higer-level NIF implementation.
///
/// ```ignore
/// #[nif]
/// fn add(a: i64, b: i64) -> i64 {
///     a + b
/// }
/// ```
#[proc_macro_attribute]
pub fn nif(args: TokenStream, input: TokenStream) -> TokenStream {
    let args = syn::parse_macro_input!(args as syn::AttributeArgs);
    let input = syn::parse_macro_input!(input as syn::ItemFn);

    nif::transcoder_decorator(args, input).into()
}

/// Implementation of the `NifStruct` macro that lets the user annotate a struct that will
/// be translated directly from an Elixir struct to a Rust struct. For example, the following
/// struct, annotated as such:
///
/// ```ignore
/// #[derive(Debug, NifStruct)]
/// #[module = "AddStruct"]
/// struct AddStruct {
///    lhs: i32,
///    rhs: i32,
/// }
/// ```
///
/// This would be translated by Rustler into:
///
/// ```elixir
/// defmodule AddStruct do
///   defstruct lhs: 0, rhs: 0
/// end
/// ```
#[proc_macro_derive(NifStruct, attributes(module, rustler))]
pub fn nif_struct(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    ex_struct::transcoder_decorator(&ast, false).into()
}

/// Implementation of the `NifException` macro that lets the user annotate a struct that will
/// be translated directly from an Elixir exception to a Rust struct. For example, the following
/// struct, annotated as such:
///
/// ```ignore
/// #[derive(Debug, NifException)]
/// #[module = "AddException"]
/// pub struct AddException {
///     message: String,
/// }
/// ```
///
/// This would be translated by Rustler into:
///
/// ```elixir
/// defmodule AddException do
///   defexception message: ""
/// end
/// ```
#[proc_macro_derive(NifException, attributes(module, rustler))]
pub fn nif_exception(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    ex_struct::transcoder_decorator(&ast, true).into()
}

/// Implementation of a macro that lets the user annotate a struct with `NifMap` so that the
/// struct can be encoded or decoded from an Elixir map. For example, the following struct
/// annotated as such:
///
/// ```ignore
/// #[derive(NifMap)]
/// struct AddMap {
///     lhs: i32,
///     rhs: i32,
/// }
/// ```
///
/// Given the values 33 and 21 for this struct, this would result, when encoded, in an elixir
/// map with two elements like:
///
/// ```elixir
/// %{lhs: 33, rhs: 21}
/// ```
#[proc_macro_derive(NifMap, attributes(rustler))]
pub fn nif_map(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    map::transcoder_decorator(&ast).into()
}

/// Implementation of a macro that lets the user annotate a struct with `NifTuple` so that the
/// struct can be encoded or decoded from an Elixir tuple. For example, the following struct
/// annotated as such:
///
/// ```ignore
/// #[derive(NifTuple)]
/// struct AddTuple {
///     lhs: i32,
///     rhs: i32,
/// }
/// ```
///
/// Given the values 33 and 21 for this struct, this would result, when encoded, in an elixir
/// tuple with two elements like:
///
/// ```elixir
/// {33, 21}
/// ```
///
/// The size of the tuple will depend on the number of elements in the struct.
#[proc_macro_derive(NifTuple, attributes(rustler))]
pub fn nif_tuple(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    tuple::transcoder_decorator(&ast).into()
}

/// Implementation of the `NifRecord` macro that lets the user annotate a struct that will
/// be translated directly from an Elixir struct to a Rust struct. For example, the following
/// struct, annotated as such:
///
/// ```ignore
/// #[derive(Debug, NifRecord)]
/// #[tag = "record"]
/// struct AddRecord {
///    lhs: i32,
///    rhs: i32,
/// }
/// ```
///
/// This would be translated by Rustler into:
///
/// ```elixir
/// defmodule AddRecord do
///   import Record
///   defrecord :record, [lhs: 1, rhs: 2]
/// end
/// ```
#[proc_macro_derive(NifRecord, attributes(tag, rustler))]
pub fn nif_record(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    record::transcoder_decorator(&ast).into()
}

/// Implementation of the `NifUnitEnum` macro that lets the user annotate an enum with a unit type
/// that will generate elixir atoms when encoded
///
/// ```ignore
/// #[derive(NifUnitEnum)]
/// enum UnitEnum {
///    FooBar,
///    Baz,
/// }
/// ```
///
/// An example usage in elixir would look like the following.
///
/// ```elixir
/// test "unit enum transcoder" do
///   assert :foo_bar == RustlerTest.unit_enum_echo(:foo_bar)
///   assert :baz == RustlerTest.unit_enum_echo(:baz)
///   assert :invalid_variant == RustlerTest.unit_enum_echo(:somethingelse)
/// end
/// ```
///
/// Note that the `:invalid_variant` atom is returned if the user tries to encode something
/// that isn't in the Rust enum.
#[proc_macro_derive(NifUnitEnum, attributes(rustler))]
pub fn nif_unit_enum(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    unit_enum::transcoder_decorator(&ast).into()
}

/// Implementation of the `NifUntaggedEnum` macro that lets the user annotate an enum that will
/// generate elixir values when decoded. This can be used for rust enums that contain data and
/// will generate a value based on the kind of data encoded. For example from the test code:
///
/// ```ignore
/// #[derive(NifUntaggedEnum)]
/// enum UntaggedEnum {
///     Foo(u32),
///     Bar(String),
///     Baz(AddStruct),
/// }
///
/// pub fn untagged_enum_echo<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult<Term<'a>> {
///     let untagged_enum: UntaggedEnum = args[0].decode()?;
///     Ok(untagged_enum.encode(env))
/// }
/// ```
///
/// This can be used from elixir in the following manner.
///
/// ```elixir
/// test "untagged enum transcoder" do
///   assert 123 == RustlerTest.untagged_enum_echo(123)
///   assert "Hello" == RustlerTest.untagged_enum_echo("Hello")
///   assert %AddStruct{lhs: 45, rhs: 123} = RustlerTest.untagged_enum_echo(%AddStruct{lhs: 45, rhs: 123})
///   assert :invalid_variant == RustlerTest.untagged_enum_echo([1,2,3,4])
/// end
/// ```
///
/// Note that the type of elixir return is dependent on the data in the enum and the actual enum
/// type is lost in the translation because Elixir has no such concept.
#[proc_macro_derive(NifUntaggedEnum, attributes(rustler))]
pub fn nif_untagged_enum(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    untagged_enum::transcoder_decorator(&ast).into()
}
<|endoftext|>


<commit_before>// Checks if the correct annotation for the efiapi ABI is passed to llvm.

// revisions:x86_64 i686 aarch64 arm riscv

// min-llvm-version 9.0

//[x86_64] compile-flags: --target x86_64-unknown-uefi
//[i686] compile-flags: --target i686-unknown-linux-musl
//[aarch64] compile-flags: --target aarch64-unknown-none
//[arm] compile-flags: --target armv7r-none-eabi
//[riscv] compile-flags: --target riscv64gc-unknown-none-elf
// compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]
#![feature(no_core, lang_items, abi_efiapi)]
#![no_core]

#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }

//x86_64: define win64cc void @has_efiapi
//i686: define void @has_efiapi
//aarch64: define void @has_efiapi
//arm: define void @has_efiapi
//riscv: define void @has_efiapi
#[no_mangle]
pub extern "efiapi" fn has_efiapi() {}
<commit_msg>Do not require extra LLVM backends for `x.py test` to pass<commit_after>// Checks if the correct annotation for the efiapi ABI is passed to llvm.

// revisions:x86_64 i686 arm

// min-llvm-version 9.0

//[x86_64] compile-flags: --target x86_64-unknown-uefi
//[i686] compile-flags: --target i686-unknown-linux-musl
//[arm] compile-flags: --target armv7r-none-eabi
// compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]
#![feature(no_core, lang_items, abi_efiapi)]
#![no_core]

#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }

//x86_64: define win64cc void @has_efiapi
//i686: define void @has_efiapi
//arm: define void @has_efiapi
#[no_mangle]
pub extern "efiapi" fn has_efiapi() {}
<|endoftext|>


<commit_before><commit_msg>Remove mention of macro_use in doc comment<commit_after><|endoftext|>


<commit_before><commit_msg>Add deserialization example (#63)<commit_after><|endoftext|>


<commit_before>use crate::utils::{
    get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, SpanlessEq,
};
use crate::utils::{higher, sugg};
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability;

declare_clippy_lint! {
    /// **What it does:** Checks for `a = a op b` or `a = b commutative_op a`
    /// patterns.
    ///
    /// **Why is this bad?** These can be written as the shorter `a op= b`.
    ///
    /// **Known problems:** While forbidden by the spec, `OpAssign` traits may have
    /// implementations that differ from the regular `Op` impl.
    ///
    /// **Example:**
    /// ```ignore
    /// let mut a = 5;
    /// ...
    /// a = a + b;
    /// ```
    pub ASSIGN_OP_PATTERN,
    style,
    "assigning the result of an operation on a variable to that same variable"
}

declare_clippy_lint! {
    /// **What it does:** Checks for `a op= a op b` or `a op= b op a` patterns.
    ///
    /// **Why is this bad?** Most likely these are bugs where one meant to write `a
    /// op= b`.
    ///
    /// **Known problems:** Clippy cannot know for sure if `a op= a op b` should have
    /// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore it suggests both.
    /// If `a op= a op b` is really the correct behaviour it should be
    /// written as `a = a op a op b` as it's less confusing.
    ///
    /// **Example:**
    /// ```ignore
    /// let mut a = 5;
    /// ...
    /// a += a + b;
    /// ```
    pub MISREFACTORED_ASSIGN_OP,
    complexity,
    "having a variable on both sides of an assign op"
}

#[derive(Copy, Clone, Default)]
pub struct AssignOps;

impl LintPass for AssignOps {
    fn get_lints(&self) -> LintArray {
        lint_array!(ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP)
    }

    fn name(&self) -> &'static str {
        "AssignOps"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
    #[allow(clippy::too_many_lines)]
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        match &expr.node {
            hir::ExprKind::AssignOp(op, lhs, rhs) => {
                if let hir::ExprKind::Binary(binop, l, r) = &rhs.node {
                    if op.node == binop.node {
                        let lint = |assignee: &hir::Expr, rhs_other: &hir::Expr| {
                            span_lint_and_then(
                                cx,
                                MISREFACTORED_ASSIGN_OP,
                                expr.span,
                                "variable appears on both sides of an assignment operation",
                                |db| {
                                    if let (Some(snip_a), Some(snip_r)) =
                                        (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span))
                                    {
                                        let a = &sugg::Sugg::hir(cx, assignee, "..");
                                        let r = &sugg::Sugg::hir(cx, rhs, "..");
                                        let long =
                                            format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r));
                                        db.span_suggestion(
                                            expr.span,
                                            &format!(
                                                "Did you mean {} = {} {} {} or {}? Consider replacing it with",
                                                snip_a,
                                                snip_a,
                                                op.node.as_str(),
                                                snip_r,
                                                long
                                            ),
                                            format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
                                            Applicability::MachineApplicable,
                                        );
                                        db.span_suggestion(
                                            expr.span,
                                            "or",
                                            long,
                                            Applicability::MachineApplicable, // snippet
                                        );
                                    }
                                },
                            );
                        };
                        // lhs op= l op r
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, l) {
                            lint(lhs, r);
                        }
                        // lhs op= l commutative_op r
                        if is_commutative(op.node) && SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, r) {
                            lint(lhs, l);
                        }
                    }
                }
            },
            hir::ExprKind::Assign(assignee, e) => {
                if let hir::ExprKind::Binary(op, l, r) = &e.node {
                    #[allow(clippy::cognitive_complexity)]
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tables.expr_ty(assignee);
                        let rty = cx.tables.expr_ty(rhs);
                        macro_rules! ops {
                            ($op:expr,
                             $cx:expr,
                             $ty:expr,
                             $rty:expr,
                             $($trait_name:ident),+) => {
                                match $op {
                                    $(hir::BinOpKind::$trait_name => {
                                        let [krate, module] = crate::utils::paths::OPS_MODULE;
                                        let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        // check that we are not inside an `impl AssignOp` of this exact operation
                                        let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
                                        if_chain! {
                                            if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
                                            if trait_ref.path.def.def_id() == trait_id;
                                            then { return; }
                                        }
                                        implements_trait($cx, $ty, trait_id, &[$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(
                            op.node,
                            cx,
                            ty,
                            rty.into(),
                            Add,
                            Sub,
                            Mul,
                            Div,
                            Rem,
                            And,
                            Or,
                            BitAnd,
                            BitOr,
                            BitXor,
                            Shr,
                            Shl
                        ) {
                            span_lint_and_then(
                                cx,
                                ASSIGN_OP_PATTERN,
                                expr.span,
                                "manual implementation of an assign operation",
                                |db| {
                                    if let (Some(snip_a), Some(snip_r)) =
                                        (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
                                    {
                                        db.span_suggestion(
                                            expr.span,
                                            "replace it with",
                                            format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
                                            Applicability::MachineApplicable,
                                        );
                                    }
                                },
                            );
                        }
                    };

                    let mut visitor = ExprVisitor {
                        assignee,
                        counter: 0,
                        cx,
                    };

                    walk_expr(&mut visitor, e);

                    if visitor.counter == 1 {
                        // a = a op b
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                            lint(assignee, r);
                        }
                        // a = b commutative_op a
                        // Limited to primitive type as these ops are know to be commutative
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r)
                            && cx.tables.expr_ty(assignee).is_primitive_ty()
                        {
                            match op.node {
                                hir::BinOpKind::Add
                                | hir::BinOpKind::Mul
                                | hir::BinOpKind::And
                                | hir::BinOpKind::Or
                                | hir::BinOpKind::BitXor
                                | hir::BinOpKind::BitAnd
                                | hir::BinOpKind::BitOr => {
                                    lint(assignee, l);
                                },
                                _ => {},
                            }
                        }
                    }
                }
            },
            _ => {},
        }
    }
}

fn is_commutative(op: hir::BinOpKind) -> bool {
    use rustc::hir::BinOpKind::*;
    match op {
        Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true,
        Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false,
    }
}

struct ExprVisitor<'a, 'tcx: 'a> {
    assignee: &'a hir::Expr,
    counter: u8,
    cx: &'a LateContext<'a, 'tcx>,
}

impl<'a, 'tcx: 'a> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
        if SpanlessEq::new(self.cx).ignore_fn().eq_expr(self.assignee, expr) {
            self.counter += 1;
        }

        walk_expr(self, expr);
    }
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::None
    }
}
<commit_msg>Rollup merge of #3852 - phansch:refactor_assign_ops, r=flip1995<commit_after>use crate::utils::{
    get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, SpanlessEq,
};
use crate::utils::{higher, sugg};
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability;

declare_clippy_lint! {
    /// **What it does:** Checks for `a = a op b` or `a = b commutative_op a`
    /// patterns.
    ///
    /// **Why is this bad?** These can be written as the shorter `a op= b`.
    ///
    /// **Known problems:** While forbidden by the spec, `OpAssign` traits may have
    /// implementations that differ from the regular `Op` impl.
    ///
    /// **Example:**
    /// ```ignore
    /// let mut a = 5;
    /// ...
    /// a = a + b;
    /// ```
    pub ASSIGN_OP_PATTERN,
    style,
    "assigning the result of an operation on a variable to that same variable"
}

declare_clippy_lint! {
    /// **What it does:** Checks for `a op= a op b` or `a op= b op a` patterns.
    ///
    /// **Why is this bad?** Most likely these are bugs where one meant to write `a
    /// op= b`.
    ///
    /// **Known problems:** Clippy cannot know for sure if `a op= a op b` should have
    /// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore it suggests both.
    /// If `a op= a op b` is really the correct behaviour it should be
    /// written as `a = a op a op b` as it's less confusing.
    ///
    /// **Example:**
    /// ```ignore
    /// let mut a = 5;
    /// ...
    /// a += a + b;
    /// ```
    pub MISREFACTORED_ASSIGN_OP,
    complexity,
    "having a variable on both sides of an assign op"
}

#[derive(Copy, Clone, Default)]
pub struct AssignOps;

impl LintPass for AssignOps {
    fn get_lints(&self) -> LintArray {
        lint_array!(ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP)
    }

    fn name(&self) -> &'static str {
        "AssignOps"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
    #[allow(clippy::too_many_lines)]
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        match &expr.node {
            hir::ExprKind::AssignOp(op, lhs, rhs) => {
                if let hir::ExprKind::Binary(binop, l, r) = &rhs.node {
                    if op.node != binop.node {
                        return;
                    }
                    // lhs op= l op r
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, l) {
                        lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, r);
                    }
                    // lhs op= l commutative_op r
                    if is_commutative(op.node) && SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, r) {
                        lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, l);
                    }
                }
            },
            hir::ExprKind::Assign(assignee, e) => {
                if let hir::ExprKind::Binary(op, l, r) = &e.node {
                    #[allow(clippy::cognitive_complexity)]
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tables.expr_ty(assignee);
                        let rty = cx.tables.expr_ty(rhs);
                        macro_rules! ops {
                            ($op:expr,
                             $cx:expr,
                             $ty:expr,
                             $rty:expr,
                             $($trait_name:ident),+) => {
                                match $op {
                                    $(hir::BinOpKind::$trait_name => {
                                        let [krate, module] = crate::utils::paths::OPS_MODULE;
                                        let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        // check that we are not inside an `impl AssignOp` of this exact operation
                                        let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
                                        if_chain! {
                                            if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
                                            if trait_ref.path.def.def_id() == trait_id;
                                            then { return; }
                                        }
                                        implements_trait($cx, $ty, trait_id, &[$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(
                            op.node,
                            cx,
                            ty,
                            rty.into(),
                            Add,
                            Sub,
                            Mul,
                            Div,
                            Rem,
                            And,
                            Or,
                            BitAnd,
                            BitOr,
                            BitXor,
                            Shr,
                            Shl
                        ) {
                            span_lint_and_then(
                                cx,
                                ASSIGN_OP_PATTERN,
                                expr.span,
                                "manual implementation of an assign operation",
                                |db| {
                                    if let (Some(snip_a), Some(snip_r)) =
                                        (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
                                    {
                                        db.span_suggestion(
                                            expr.span,
                                            "replace it with",
                                            format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
                                            Applicability::MachineApplicable,
                                        );
                                    }
                                },
                            );
                        }
                    };

                    let mut visitor = ExprVisitor {
                        assignee,
                        counter: 0,
                        cx,
                    };

                    walk_expr(&mut visitor, e);

                    if visitor.counter == 1 {
                        // a = a op b
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                            lint(assignee, r);
                        }
                        // a = b commutative_op a
                        // Limited to primitive type as these ops are know to be commutative
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r)
                            && cx.tables.expr_ty(assignee).is_primitive_ty()
                        {
                            match op.node {
                                hir::BinOpKind::Add
                                | hir::BinOpKind::Mul
                                | hir::BinOpKind::And
                                | hir::BinOpKind::Or
                                | hir::BinOpKind::BitXor
                                | hir::BinOpKind::BitAnd
                                | hir::BinOpKind::BitOr => {
                                    lint(assignee, l);
                                },
                                _ => {},
                            }
                        }
                    }
                }
            },
            _ => {},
        }
    }
}

fn lint_misrefactored_assign_op(
    cx: &LateContext<'_, '_>,
    expr: &hir::Expr,
    op: hir::BinOp,
    rhs: &hir::Expr,
    assignee: &hir::Expr,
    rhs_other: &hir::Expr,
) {
    span_lint_and_then(
        cx,
        MISREFACTORED_ASSIGN_OP,
        expr.span,
        "variable appears on both sides of an assignment operation",
        |db| {
            if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
                let a = &sugg::Sugg::hir(cx, assignee, "..");
                let r = &sugg::Sugg::hir(cx, rhs, "..");
                let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r));
                db.span_suggestion(
                    expr.span,
                    &format!(
                        "Did you mean {} = {} {} {} or {}? Consider replacing it with",
                        snip_a,
                        snip_a,
                        op.node.as_str(),
                        snip_r,
                        long
                    ),
                    format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
                    Applicability::MachineApplicable,
                );
                db.span_suggestion(
                    expr.span,
                    "or",
                    long,
                    Applicability::MachineApplicable, // snippet
                );
            }
        },
    );
}

fn is_commutative(op: hir::BinOpKind) -> bool {
    use rustc::hir::BinOpKind::*;
    match op {
        Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true,
        Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false,
    }
}

struct ExprVisitor<'a, 'tcx: 'a> {
    assignee: &'a hir::Expr,
    counter: u8,
    cx: &'a LateContext<'a, 'tcx>,
}

impl<'a, 'tcx: 'a> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
        if SpanlessEq::new(self.cx).ignore_fn().eq_expr(self.assignee, expr) {
            self.counter += 1;
        }

        walk_expr(self, expr);
    }
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::None
    }
}
<|endoftext|>


<commit_before>pub use std::libc::*;
pub use std::libc::types::os::arch::extra::*;

pub type ATOM = WORD;
pub type UINT = c_uint;
pub type LONG = c_long;

// 32-bit specific
pub type UINT_PTR = c_uint;
pub type LONG_PTR = c_long;
pub type ULONG_PTR = c_ulong;

pub type HANDLE = PVOID;

pub type HBRUSH = HANDLE;
pub type HCURSOR = HICON;
pub type HMENU = HANDLE;
pub type HICON = HANDLE;
pub type HINSTANCE = HANDLE;
pub type HWND = HANDLE;
pub type HDC = HANDLE;

pub type WPARAM = UINT_PTR;
pub type LPARAM = LONG_PTR;

pub type PVOID = *c_void;

// extern fn(HWND, UINT, WPARAM, LPARAM) -> LRESULT
pub type WNDPROC = *u8;

pub struct WNDCLASSEX {
    cbSize: UINT,
    style: UINT,
    lpfnWndProc: WNDPROC,
    cbClsExtra: c_int,
    cbWndExtra: c_int,
    hInstance: HINSTANCE,
    hIcon: HICON,
    hCursor: HCURSOR,
    hbrBackground: HBRUSH,
    lpszMenuName: LPCWSTR,
    lpszClassName: LPCWSTR,
    hIconSm: HICON,
}

pub struct POINT {
    x: LONG,
    y: LONG,
}

pub struct MSG {
    hwnd: HWND,
    message: UINT,
    wParam: WPARAM,
    lParam: LPARAM,
    time: DWORD,
    pt: POINT,
}

pub struct RECT {
    left: LONG,
    top: LONG,
    right: LONG,
    bottom: LONG,
}

pub struct PAINTSTRUCT {
    hdc: HDC,
    fErase: BOOL,
    rcPaint: RECT,
    fRestore: BOOL,
    fIncUpdate: BOOL,
    rgbReserved: *[BYTE, ..32],
}

pub mod kernel32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
    }
}

pub mod user32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn CreateWindowExW(extrastyle: DWORD, classname: LPCWSTR,
                windowname: LPCWSTR, style: DWORD,
                x: c_int, y: c_int, width: c_int, height: c_int,
                parent: HWND, menu: HMENU, instance: HINSTANCE, param: LPVOID
        ) -> HWND;

        unsafe fn ShowWindow(hwnd: HWND, nCmdShow: c_int) -> BOOL;

        unsafe fn UpdateWindow(hwnd: HWND) -> BOOL;

        unsafe fn BeginPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> HDC;

        unsafe fn EndPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> BOOL;

        unsafe fn MessageBoxW(
                hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT
        ) -> c_int;

        unsafe fn RegisterClassExW(lpwcx: *WNDCLASSEX) -> ATOM;

        unsafe fn DefWindowProcW(
                hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM
        ) -> LRESULT;

        unsafe fn GetMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT
        ) -> BOOL;

        unsafe fn PeekMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT, wRemoveMsg: UINT
        ) -> BOOL;

        unsafe fn TranslateMessage(lpMsg: *MSG) -> BOOL;

        unsafe fn DispatchMessageW(lpMsg: *MSG) -> LRESULT;

        // 32-bit only
        unsafe fn GetClassLongW(hwnd: HWND, nIndex: c_int) -> DWORD;

        // 32-bit only
        unsafe fn SetClassLongW(
                hwnd: HWND, nIndex: c_int, dwNewLong: LONG
        ) -> DWORD;
    }
}
<commit_msg>ll: add struct CREATESTRUCT<commit_after>pub use std::libc::*;
pub use std::libc::types::os::arch::extra::*;

pub type ATOM = WORD;
pub type UINT = c_uint;
pub type LONG = c_long;

// 32-bit specific
pub type UINT_PTR = c_uint;
pub type LONG_PTR = c_long;
pub type ULONG_PTR = c_ulong;

pub type HANDLE = PVOID;

pub type HBRUSH = HANDLE;
pub type HCURSOR = HICON;
pub type HMENU = HANDLE;
pub type HICON = HANDLE;
pub type HINSTANCE = HANDLE;
pub type HWND = HANDLE;
pub type HDC = HANDLE;

pub type WPARAM = UINT_PTR;
pub type LPARAM = LONG_PTR;

pub type PVOID = *c_void;

// extern fn(HWND, UINT, WPARAM, LPARAM) -> LRESULT
pub type WNDPROC = *u8;

pub struct WNDCLASSEX {
    cbSize: UINT,
    style: UINT,
    lpfnWndProc: WNDPROC,
    cbClsExtra: c_int,
    cbWndExtra: c_int,
    hInstance: HINSTANCE,
    hIcon: HICON,
    hCursor: HCURSOR,
    hbrBackground: HBRUSH,
    lpszMenuName: LPCWSTR,
    lpszClassName: LPCWSTR,
    hIconSm: HICON,
}

pub struct CREATESTRUCT {
    lpCreateParams: LPVOID,
    hInstance: HINSTANCE,
    hMenu: HMENU,
    hwndParent: HWND,
    cy: c_int,
    cx: c_int,
    y: c_int,
    x: c_int,
    style: LONG,
    lpszName: LPCWSTR,
    lpszClass: LPCWSTR,
    dwExStyle: DWORD,
}

pub struct POINT {
    x: LONG,
    y: LONG,
}

pub struct MSG {
    hwnd: HWND,
    message: UINT,
    wParam: WPARAM,
    lParam: LPARAM,
    time: DWORD,
    pt: POINT,
}

pub struct RECT {
    left: LONG,
    top: LONG,
    right: LONG,
    bottom: LONG,
}

pub struct PAINTSTRUCT {
    hdc: HDC,
    fErase: BOOL,
    rcPaint: RECT,
    fRestore: BOOL,
    fIncUpdate: BOOL,
    rgbReserved: *[BYTE, ..32],
}

pub mod kernel32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
    }
}

pub mod user32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn CreateWindowExW(extrastyle: DWORD, classname: LPCWSTR,
                windowname: LPCWSTR, style: DWORD,
                x: c_int, y: c_int, width: c_int, height: c_int,
                parent: HWND, menu: HMENU, instance: HINSTANCE, param: LPVOID
        ) -> HWND;

        unsafe fn ShowWindow(hwnd: HWND, nCmdShow: c_int) -> BOOL;

        unsafe fn UpdateWindow(hwnd: HWND) -> BOOL;

        unsafe fn BeginPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> HDC;

        unsafe fn EndPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> BOOL;

        unsafe fn MessageBoxW(
                hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT
        ) -> c_int;

        unsafe fn RegisterClassExW(lpwcx: *WNDCLASSEX) -> ATOM;

        unsafe fn DefWindowProcW(
                hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM
        ) -> LRESULT;

        unsafe fn GetMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT
        ) -> BOOL;

        unsafe fn PeekMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT, wRemoveMsg: UINT
        ) -> BOOL;

        unsafe fn TranslateMessage(lpMsg: *MSG) -> BOOL;

        unsafe fn DispatchMessageW(lpMsg: *MSG) -> LRESULT;

        // 32-bit only
        unsafe fn GetClassLongW(hwnd: HWND, nIndex: c_int) -> DWORD;

        // 32-bit only
        unsafe fn SetClassLongW(
                hwnd: HWND, nIndex: c_int, dwNewLong: LONG
        ) -> DWORD;
    }
}
<|endoftext|>


<commit_before>use std::io;

/// Apply Erathostenes's sieve to the supplied array
///
/// # Arguments
///
/// * `dest` - the destination slice to fill with the sieve. This is
///   assumed to be filled with "true" before being handed to this
///   method.
pub fn prime_sieve(dest: &mut[bool]) {
    if dest.len() >= 1 {
        dest[0] = false;
    }

    if dest.len() >= 2 {
        dest[1] = false;
    }

    let limit = (dest.len() as f64).sqrt() as usize;

    for i in 1..(limit + 1) {
        if !dest[i] {
            continue
        }

        for j in ((i * i)..(dest.len())).step_by(i) {
            dest[j] = false;
        }
    }
}

/// Greatest common divisor
pub fn gcd(a: i32, b: i32) -> i32 {
    if a < b {
        gcd(b, a)
    } else {
        if a % b == 0 {
            b
        } else {
            gcd(a % b, b)
        }
    }
}

/// Least common multiple
pub fn lcm(a: i32, b: i32) -> i32 {
    a * b / gcd(a, b)
}

/// Solution trait
///
/// Every day's solution should implement this function so that it can
/// be easily run from the main program.
pub trait Solution {
    /// Solve the first part of the day
    fn part1(&mut self, input: &mut io::Read) -> String;

    /// Solve the second part of the day
    fn part2(&mut self, input: &mut io::Read) -> String;
}

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

    #[test]
    fn test_prime_sieve() {
        let mut input = [true; 10];
        prime_sieve(&mut input);

        let output = [
            false, false,
            true, true,
            false, true,
            false, true,
            false, false
        ];

        assert_eq!(output, input);
    }

    #[test]
    fn test_gcd() {
        assert_eq!(12, gcd(24, 36));
        assert_eq!(1, gcd(1, 7));
    }

    #[test]
    fn test_lcm() {
        assert_eq!(12, lcm(6, 4));
    }
}
<commit_msg>Generify gcd/lcm.<commit_after>use std::io;
use std::ops;
use std::cmp;

/// Apply Erathostenes's sieve to the supplied array
///
/// # Arguments
///
/// * `dest` - the destination slice to fill with the sieve. This is
///   assumed to be filled with "true" before being handed to this
///   method.
pub fn prime_sieve(dest: &mut[bool]) {
    if dest.len() >= 1 {
        dest[0] = false;
    }

    if dest.len() >= 2 {
        dest[1] = false;
    }

    let limit = (dest.len() as f64).sqrt() as usize;

    for i in 1..(limit + 1) {
        if !dest[i] {
            continue
        }

        for j in ((i * i)..(dest.len())).step_by(i) {
            dest[j] = false;
        }
    }
}

/// Greatest common divisor
pub fn gcd<T: ops::Rem<Output = T> + cmp::PartialOrd + std::convert::From<i32> + Copy>(a: T, b: T) -> T {
    if a < b {
        gcd(b, a)
    } else {
        if a % b == T::from(0) {
            b
        } else {
            gcd(a % b, b)
        }
    }
}

/// Least common multiple
pub fn lcm<T: ops::Rem<Output = T> + ops::Mul<Output = T> + ops::Div<Output = T> + cmp::PartialOrd + std::convert::From<i32> + Copy>(a: T, b: T) -> T {
    a * b / gcd(a, b)
}

/// Solution trait
///
/// Every day's solution should implement this function so that it can
/// be easily run from the main program.
pub trait Solution {
    /// Solve the first part of the day
    fn part1(&mut self, input: &mut io::Read) -> String;

    /// Solve the second part of the day
    fn part2(&mut self, input: &mut io::Read) -> String;
}

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

    #[test]
    fn test_prime_sieve() {
        let mut input = [true; 10];
        prime_sieve(&mut input);

        let output = [
            false, false,
            true, true,
            false, true,
            false, true,
            false, false
        ];

        assert_eq!(output, input);
    }

    #[test]
    fn test_gcd() {
        assert_eq!(12, gcd(24, 36));
        assert_eq!(1, gcd(1, 7));
    }

    #[test]
    fn test_lcm() {
        assert_eq!(12, lcm(6, 4));
    }
}
<|endoftext|>


<commit_before>use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;
use std::marker::PhantomData;
use std::str::FromStr;

use nom::Finish;
use nom::IResult;

pub struct LineIter<'a> {
    reader: BufReader<&'a mut dyn Read>,
    buffer: String,
}

impl<'a> LineIter<'a> {
    pub fn new(input: &'a mut dyn Read) -> Self {
        Self {
            reader: BufReader::new(input),
            buffer: String::new(),
        }
    }

    /// Get the next line, or None
    ///
    /// This is deliberately not an [Iterator] impl as those cannot hand out references to self.
    pub fn next(&mut self) -> Option<&str> {
        self.buffer.clear();

        if matches!(self.reader.read_line(&mut self.buffer), Ok(n) if n > 0) {
            Some(self.buffer.trim_end_matches('\n'))
        } else {
            None
        }
    }
}

/// Line-based iterator/parser
///
/// For each line of the input, attempt to parse it as the requested type. Iteration is stopped on
/// the first IO error or parse error, silently. Leading and trailing whitespace is stripped before
/// attempting to parse.
pub struct LineParser<'a, I>
where
    I: FromStr,
{
    iter: LineIter<'a>,
    _data: PhantomData<I>,
}

impl<'a, I: FromStr> LineParser<'a, I> {
    pub fn new(input: &'a mut dyn Read) -> Self {
        Self {
            iter: LineIter::new(input),
            _data: PhantomData,
        }
    }
}

impl<I: FromStr> Iterator for LineParser<'_, I> {
    type Item = I;

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()?.parse().ok()
    }
}

impl<'a, I: FromStr> From<LineIter<'a>> for LineParser<'a, I> {
    fn from(iter: LineIter<'a>) -> Self {
        Self {
            iter,
            _data: PhantomData,
        }
    }
}

/// Return two arguments in their natural PartialOrd order
pub fn ordered<O: PartialOrd>(a: O, b: O) -> (O, O) {
    if a < b {
        (a, b)
    } else {
        (b, a)
    }
}

pub fn read_input<I, P, O>(mut input: I, parser: P) -> O
where
    I: Read,
    P: for<'a> FnOnce(&'a [u8]) -> IResult<&'a [u8], O>,
{
    let mut buffer = Vec::new();
    input.read_to_end(&mut buffer).unwrap();

    match parser(&buffer).finish() {
        Ok((_, output)) => output,
        Err(err) => {
            panic!(
                "Failed to parse input with error {:?} at \"{}\"",
                err.code,
                String::from_utf8_lossy(err.input)
            );
        }
    }
}

#[derive(Default)]
pub struct BitSet {
    buffer: Vec<u32>,
}

impl BitSet {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn with_capacity(capacity: usize) -> Self {
        let buffer = Vec::with_capacity(capacity / 32);

        Self { buffer }
    }

    fn convert_value(value: usize) -> (usize, u32) {
        let chunk = value / 32;
        let bit = 1 << (31 - (value % 32));

        (chunk, bit)
    }

    pub fn insert(&mut self, value: usize) -> bool {
        let (chunk, bit) = Self::convert_value(value);

        if self.buffer.len() <= chunk + 1 {
            self.buffer.resize(chunk + 1, 0);
        }

        let not_present = self.buffer[chunk] & bit;

        self.buffer[chunk] |= bit;

        not_present == 0
    }

    pub fn len(&self) -> usize {
        self.buffer.iter().map(|c| c.count_ones() as usize).sum()
    }

    pub fn contains(&self, value: usize) -> bool {
        let (chunk, bit) = Self::convert_value(value);

        self.buffer
            .get(chunk)
            .map(|&c| c & bit != 0)
            .unwrap_or(false)
    }
}
<commit_msg>Slightly more efficiently pre-allocate bitsets<commit_after>use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;
use std::marker::PhantomData;
use std::str::FromStr;

use nom::Finish;
use nom::IResult;

pub struct LineIter<'a> {
    reader: BufReader<&'a mut dyn Read>,
    buffer: String,
}

impl<'a> LineIter<'a> {
    pub fn new(input: &'a mut dyn Read) -> Self {
        Self {
            reader: BufReader::new(input),
            buffer: String::new(),
        }
    }

    /// Get the next line, or None
    ///
    /// This is deliberately not an [Iterator] impl as those cannot hand out references to self.
    pub fn next(&mut self) -> Option<&str> {
        self.buffer.clear();

        if matches!(self.reader.read_line(&mut self.buffer), Ok(n) if n > 0) {
            Some(self.buffer.trim_end_matches('\n'))
        } else {
            None
        }
    }
}

/// Line-based iterator/parser
///
/// For each line of the input, attempt to parse it as the requested type. Iteration is stopped on
/// the first IO error or parse error, silently. Leading and trailing whitespace is stripped before
/// attempting to parse.
pub struct LineParser<'a, I>
where
    I: FromStr,
{
    iter: LineIter<'a>,
    _data: PhantomData<I>,
}

impl<'a, I: FromStr> LineParser<'a, I> {
    pub fn new(input: &'a mut dyn Read) -> Self {
        Self {
            iter: LineIter::new(input),
            _data: PhantomData,
        }
    }
}

impl<I: FromStr> Iterator for LineParser<'_, I> {
    type Item = I;

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()?.parse().ok()
    }
}

impl<'a, I: FromStr> From<LineIter<'a>> for LineParser<'a, I> {
    fn from(iter: LineIter<'a>) -> Self {
        Self {
            iter,
            _data: PhantomData,
        }
    }
}

/// Return two arguments in their natural PartialOrd order
pub fn ordered<O: PartialOrd>(a: O, b: O) -> (O, O) {
    if a < b {
        (a, b)
    } else {
        (b, a)
    }
}

pub fn read_input<I, P, O>(mut input: I, parser: P) -> O
where
    I: Read,
    P: for<'a> FnOnce(&'a [u8]) -> IResult<&'a [u8], O>,
{
    let mut buffer = Vec::new();
    input.read_to_end(&mut buffer).unwrap();

    match parser(&buffer).finish() {
        Ok((_, output)) => output,
        Err(err) => {
            panic!(
                "Failed to parse input with error {:?} at \"{}\"",
                err.code,
                String::from_utf8_lossy(err.input)
            );
        }
    }
}

#[derive(Default)]
pub struct BitSet {
    buffer: Vec<u32>,
}

impl BitSet {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn with_capacity(capacity: usize) -> Self {
        let buffer = vec![0; capacity / 32];

        Self { buffer }
    }

    fn convert_value(value: usize) -> (usize, u32) {
        let chunk = value / 32;
        let bit = 1 << (31 - (value % 32));

        (chunk, bit)
    }

    pub fn insert(&mut self, value: usize) -> bool {
        let (chunk, bit) = Self::convert_value(value);

        if self.buffer.len() <= chunk + 1 {
            self.buffer.resize(chunk + 1, 0);
        }

        let not_present = self.buffer[chunk] & bit;

        self.buffer[chunk] |= bit;

        not_present == 0
    }

    pub fn len(&self) -> usize {
        self.buffer.iter().map(|c| c.count_ones() as usize).sum()
    }

    pub fn contains(&self, value: usize) -> bool {
        let (chunk, bit) = Self::convert_value(value);

        self.buffer
            .get(chunk)
            .map(|&c| c & bit != 0)
            .unwrap_or(false)
    }
}
<|endoftext|>


<commit_before>use std::any::Any;
use std::collections::VecDeque;
use std::fmt;
use std::sync::{Arc, Mutex};

use futures::{future, Future};

use base::types::{ArcType, Type};

use api::generic::A;
use api::{
    primitive, AsyncPushable, Function, FunctionRef, FutureResult, Generic, Getable, OpaqueValue,
    OwnedFunction, Pushable, RuntimeResult, VmType, WithVM, IO,
};
use gc::{Gc, GcPtr, Traverseable};
use stack::{StackFrame, State};
use thread::{OwnedContext, ThreadInternal};
use types::VmInt;
use value::{Callable, GcStr, Userdata, ValueRepr};
use vm::{RootedThread, Status, Thread};
use {Error, ExternModule, Result as VmResult};

pub struct Sender<T> {
    // No need to traverse this thread reference as any thread having a reference to this `Sender`
    // would also directly own a reference to the `Thread`
    thread: GcPtr<Thread>,
    queue: Arc<Mutex<VecDeque<T>>>,
}

impl<T> Userdata for Sender<T> where T: Any + Send + Sync + fmt::Debug + Traverseable {}

impl<T> fmt::Debug for Sender<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", *self.queue.lock().unwrap())
    }
}

impl<T> Traverseable for Sender<T> {
    fn traverse(&self, _gc: &mut Gc) {
        // No need to traverse in Sender as values can only be accessed through Receiver
    }
}

impl<T> Sender<T> {
    fn send(&self, value: T) {
        self.queue.lock().unwrap().push_back(value);
    }
}

impl<T: Traverseable> Traverseable for Receiver<T> {
    fn traverse(&self, gc: &mut Gc) {
        self.queue.lock().unwrap().traverse(gc);
    }
}

pub struct Receiver<T> {
    queue: Arc<Mutex<VecDeque<T>>>,
}

impl<T> Userdata for Receiver<T> where T: Any + Send + Sync + fmt::Debug + Traverseable {}

impl<T> fmt::Debug for Receiver<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", *self.queue.lock().unwrap())
    }
}

impl<T> Receiver<T> {
    fn try_recv(&self) -> Result<T, ()> {
        self.queue.lock().unwrap().pop_front().ok_or(())
    }
}

impl<T: VmType> VmType for Sender<T>
where
    T::Type: Sized,
{
    type Type = Sender<T::Type>;
    fn make_type(vm: &Thread) -> ArcType {
        let symbol = vm
            .global_env()
            .get_env()
            .find_type_info("Sender")
            .unwrap()
            .name
            .clone();
        Type::app(Type::ident(symbol), collect![T::make_type(vm)])
    }
}

impl<T: VmType> VmType for Receiver<T>
where
    T::Type: Sized,
{
    type Type = Receiver<T::Type>;
    fn make_type(vm: &Thread) -> ArcType {
        let symbol = vm
            .global_env()
            .get_env()
            .find_type_info("Receiver")
            .unwrap()
            .name
            .clone();
        Type::app(Type::ident(symbol), collect![T::make_type(vm)])
    }
}

field_decl!{ sender, receiver }

pub type ChannelRecord<S, R> = record_type!(sender => S, receiver => R);

/// FIXME The dummy `a` argument should not be needed to ensure that the channel can only be used
/// with a single type
fn channel(
    WithVM { vm, .. }: WithVM<Generic<A>>,
) -> ChannelRecord<Sender<Generic<A>>, Receiver<Generic<A>>> {
    let sender = Sender {
        thread: unsafe { GcPtr::from_raw(vm) },
        queue: Arc::new(Mutex::new(VecDeque::new())),
    };
    let receiver = Receiver {
        queue: sender.queue.clone(),
    };
    record_no_decl!(sender => sender, receiver => receiver)
}

fn recv(receiver: &Receiver<Generic<A>>) -> Result<Generic<A>, ()> {
    receiver.try_recv().map_err(|_| ())
}

fn send(sender: &Sender<Generic<A>>, value: Generic<A>) -> Result<(), ()> {
    unsafe {
        let value = sender
            .thread
            .deep_clone_value(&sender.thread, value.get_value())
            .map_err(|_| ())?;
        Ok(sender.send(Generic::from(value)))
    }
}

extern "C" fn resume(vm: &Thread) -> Status {
    let mut context = vm.context();
    let value = StackFrame::current(&mut context.stack)[0].get_repr();
    match value {
        ValueRepr::Thread(child) => {
            let lock = StackFrame::current(&mut context.stack).into_lock();
            drop(context);
            let result = child.resume();
            context = vm.context();
            context.stack.release_lock(lock);
            match result {
                Ok(child_context) => {
                    // Prevent dead lock if the following status_push call allocates
                    drop(child_context);

                    let value: Result<(), &str> = Ok(());
                    value.status_push(vm, &mut context)
                }
                Err(Error::Dead) => {
                    let value: Result<(), &str> = Err("Attempted to resume a dead thread");
                    value.status_push(vm, &mut context)
                }
                Err(err) => {
                    let fmt = format!("{}", err);
                    let result = unsafe {
                        ValueRepr::String(GcStr::from_utf8_unchecked(
                            context.alloc_ignore_limit(fmt.as_bytes()),
                        ))
                    };
                    context.stack.push(result);
                    Status::Error
                }
            }
        }
        _ => unreachable!(),
    }
}

extern "C" fn yield_(_vm: &Thread) -> Status {
    Status::Yield
}

fn spawn<'vm>(
    value: WithVM<'vm, Function<&'vm Thread, fn(())>>,
) -> RuntimeResult<RootedThread, Error> {
    spawn_(value).into()
}
fn spawn_<'vm>(value: WithVM<'vm, Function<&'vm Thread, fn(())>>) -> VmResult<RootedThread> {
    let thread = value.vm.new_thread()?;
    {
        let mut context = thread.context();
        let callable = match value.value.get_variant().0 {
            ValueRepr::Closure(c) => State::Closure(c),
            ValueRepr::Function(c) => State::Extern(c),
            _ => State::Unknown,
        };
        value.value.push(value.vm, &mut context)?;
        context.stack.push(ValueRepr::Int(0));
        StackFrame::current(&mut context.stack).enter_scope(1, callable);
    }
    Ok(thread)
}

type Action = fn(()) -> OpaqueValue<RootedThread, IO<Generic<A>>>;

#[cfg(target_arch = "wasm32")]
fn spawn_on<'vm>(
    _thread: RootedThread,
    _action: WithVM<'vm, FunctionRef<Action>>,
) -> IO<OpaqueValue<&'vm Thread, IO<Generic<A>>>> {
    IO::Exception("spawn_on requires the `tokio` crate".to_string())
}

#[cfg(not(target_arch = "wasm32"))]
fn spawn_on<'vm>(
    thread: RootedThread,
    action: WithVM<'vm, FunctionRef<Action>>,
) -> IO<OpaqueValue<&'vm Thread, IO<Generic<A>>>> {
    struct SpawnFuture<F>(future::Shared<F>)
    where
        F: Future;

    impl<F> fmt::Debug for SpawnFuture<F>
    where
        F: Future,
    {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "Future")
        }
    }

    impl<F> Userdata for SpawnFuture<F> where F: Future + Send + 'static {}

    impl<F> Traverseable for SpawnFuture<F>
    where
        F: Future,
    {
        fn traverse(&self, _: &mut Gc) {}
    }

    impl<F> VmType for SpawnFuture<F>
    where
        F: Future,
    {
        type Type = Generic<A>;
    }

    fn push_future_wrapper<G>(vm: &Thread, context: &mut OwnedContext, _: &G)
    where
        G: Future<Item = OpaqueValue<RootedThread, IO<Generic<A>>>, Error = Error> + Send + 'static,
    {
        extern "C" fn future_wrapper<F>(vm: &Thread) -> Status
        where
            F: Future<Item = OpaqueValue<RootedThread, IO<Generic<A>>>, Error = Error>
                + Send
                + 'static,
        {
            let mut context = vm.context();
            let value = StackFrame::current(&mut context.stack)[0].get_repr();

            match value {
                ValueRepr::Userdata(data) => {
                    let data = data.downcast_ref::<SpawnFuture<F>>().unwrap();
                    let future = data.0.clone();
                    let lock = StackFrame::current(&mut context.stack).insert_lock();
                    AsyncPushable::async_status_push(
                        FutureResult::new(
                            future.map(|v| (*v).clone()).map_err(|err| (*err).clone()),
                        ),
                        vm,
                        &mut context,
                        lock,
                    )
                }
                _ => unreachable!(),
            }
        }

        type FutureArg = ();
        primitive::<fn(FutureArg) -> IO<Generic<A>>>("unknown", future_wrapper::<G>)
            .push(vm, context)
            .unwrap();
    }
    use value::PartialApplicationDataDef;

    let WithVM { vm, value: action } = action;
    let mut action = OwnedFunction::<Action>::from_value(&thread, action.get_variant());

    let future = future::lazy(move || action.call_async(()));

    let mut context = vm.context();

    push_future_wrapper(vm, &mut context, &future);

    let callable = match context.stack[context.stack.len() - 1].get_repr() {
        ValueRepr::Function(ext) => Callable::Extern(ext),
        _ => unreachable!(),
    };

    SpawnFuture(future.shared()).push(vm, &mut context).unwrap();
    let fields = [context.stack.get_values().last().unwrap().clone()];
    let def = PartialApplicationDataDef(callable, &fields);
    let value = ValueRepr::PartialApplication(context.alloc_with(vm, def).unwrap()).into();

    context.stack.pop_many(2);

    // TODO Remove rooting here
    IO::Value(OpaqueValue::from_value(vm.root_value(value)))
}

fn new_thread(WithVM { vm, .. }: WithVM<()>) -> IO<RootedThread> {
    match vm.new_thread() {
        Ok(thread) => IO::Value(thread),
        Err(err) => IO::Exception(err.to_string()),
    }
}

fn sleep(ms: VmInt) -> IO<()> {
    use std::time::Duration;
    ::std::thread::sleep(Duration::from_millis(ms as u64));
    IO::Value(())
}

fn interrupt(thread: RootedThread) -> IO<()> {
    thread.interrupt();
    IO::Value(())
}

mod std {
    pub use channel;
    pub mod thread {
        pub use channel as prim;
    }
}

pub fn load_channel<'vm>(vm: &'vm Thread) -> VmResult<ExternModule> {
    let _ = vm.register_type::<Sender<A>>("Sender", &["a"]);
    let _ = vm.register_type::<Receiver<A>>("Receiver", &["a"]);

    ExternModule::new(
        vm,
        record!{
            type Sender a => Sender<A>,
            type Receiver a => Sender<A>,
            channel => primitive!(1 std::channel::channel),
            recv => primitive!(1 std::channel::recv),
            send => primitive!(2 std::channel::send),
        },
    )
}

pub fn load_thread<'vm>(vm: &'vm Thread) -> VmResult<ExternModule> {
    ExternModule::new(
        vm,
        record!{
            resume => primitive::<fn(&'vm Thread) -> Result<(), String>>("std.thread.prim.resume", resume),
            (yield_ "yield") => primitive::<fn(())>("std.thread.prim.yield", yield_),
            spawn => primitive!(1 std::thread::prim::spawn),
            spawn_on => primitive!(2 std::thread::prim::spawn_on),
            new_thread => primitive!(1 std::thread::prim::new_thread),
            interrupt => primitive!(1 std::thread::prim::interrupt),
            sleep => primitive!(1 std::thread::prim::sleep)
        },
    )
}
<commit_msg>Add bounds needed due to a unsound fix of Shared<commit_after>use std::any::Any;
use std::collections::VecDeque;
use std::fmt;
use std::sync::{Arc, Mutex};

use futures::{future, Future};

use base::types::{ArcType, Type};

use api::generic::A;
use api::{
    primitive, AsyncPushable, Function, FunctionRef, FutureResult, Generic, Getable, OpaqueValue,
    OwnedFunction, Pushable, RuntimeResult, VmType, WithVM, IO,
};
use gc::{Gc, GcPtr, Traverseable};
use stack::{StackFrame, State};
use thread::{OwnedContext, ThreadInternal};
use types::VmInt;
use value::{Callable, GcStr, Userdata, ValueRepr};
use vm::{RootedThread, Status, Thread};
use {Error, ExternModule, Result as VmResult};

pub struct Sender<T> {
    // No need to traverse this thread reference as any thread having a reference to this `Sender`
    // would also directly own a reference to the `Thread`
    thread: GcPtr<Thread>,
    queue: Arc<Mutex<VecDeque<T>>>,
}

impl<T> Userdata for Sender<T> where T: Any + Send + Sync + fmt::Debug + Traverseable {}

impl<T> fmt::Debug for Sender<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", *self.queue.lock().unwrap())
    }
}

impl<T> Traverseable for Sender<T> {
    fn traverse(&self, _gc: &mut Gc) {
        // No need to traverse in Sender as values can only be accessed through Receiver
    }
}

impl<T> Sender<T> {
    fn send(&self, value: T) {
        self.queue.lock().unwrap().push_back(value);
    }
}

impl<T: Traverseable> Traverseable for Receiver<T> {
    fn traverse(&self, gc: &mut Gc) {
        self.queue.lock().unwrap().traverse(gc);
    }
}

pub struct Receiver<T> {
    queue: Arc<Mutex<VecDeque<T>>>,
}

impl<T> Userdata for Receiver<T> where T: Any + Send + Sync + fmt::Debug + Traverseable {}

impl<T> fmt::Debug for Receiver<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", *self.queue.lock().unwrap())
    }
}

impl<T> Receiver<T> {
    fn try_recv(&self) -> Result<T, ()> {
        self.queue.lock().unwrap().pop_front().ok_or(())
    }
}

impl<T: VmType> VmType for Sender<T>
where
    T::Type: Sized,
{
    type Type = Sender<T::Type>;
    fn make_type(vm: &Thread) -> ArcType {
        let symbol = vm
            .global_env()
            .get_env()
            .find_type_info("Sender")
            .unwrap()
            .name
            .clone();
        Type::app(Type::ident(symbol), collect![T::make_type(vm)])
    }
}

impl<T: VmType> VmType for Receiver<T>
where
    T::Type: Sized,
{
    type Type = Receiver<T::Type>;
    fn make_type(vm: &Thread) -> ArcType {
        let symbol = vm
            .global_env()
            .get_env()
            .find_type_info("Receiver")
            .unwrap()
            .name
            .clone();
        Type::app(Type::ident(symbol), collect![T::make_type(vm)])
    }
}

field_decl!{ sender, receiver }

pub type ChannelRecord<S, R> = record_type!(sender => S, receiver => R);

/// FIXME The dummy `a` argument should not be needed to ensure that the channel can only be used
/// with a single type
fn channel(
    WithVM { vm, .. }: WithVM<Generic<A>>,
) -> ChannelRecord<Sender<Generic<A>>, Receiver<Generic<A>>> {
    let sender = Sender {
        thread: unsafe { GcPtr::from_raw(vm) },
        queue: Arc::new(Mutex::new(VecDeque::new())),
    };
    let receiver = Receiver {
        queue: sender.queue.clone(),
    };
    record_no_decl!(sender => sender, receiver => receiver)
}

fn recv(receiver: &Receiver<Generic<A>>) -> Result<Generic<A>, ()> {
    receiver.try_recv().map_err(|_| ())
}

fn send(sender: &Sender<Generic<A>>, value: Generic<A>) -> Result<(), ()> {
    unsafe {
        let value = sender
            .thread
            .deep_clone_value(&sender.thread, value.get_value())
            .map_err(|_| ())?;
        Ok(sender.send(Generic::from(value)))
    }
}

extern "C" fn resume(vm: &Thread) -> Status {
    let mut context = vm.context();
    let value = StackFrame::current(&mut context.stack)[0].get_repr();
    match value {
        ValueRepr::Thread(child) => {
            let lock = StackFrame::current(&mut context.stack).into_lock();
            drop(context);
            let result = child.resume();
            context = vm.context();
            context.stack.release_lock(lock);
            match result {
                Ok(child_context) => {
                    // Prevent dead lock if the following status_push call allocates
                    drop(child_context);

                    let value: Result<(), &str> = Ok(());
                    value.status_push(vm, &mut context)
                }
                Err(Error::Dead) => {
                    let value: Result<(), &str> = Err("Attempted to resume a dead thread");
                    value.status_push(vm, &mut context)
                }
                Err(err) => {
                    let fmt = format!("{}", err);
                    let result = unsafe {
                        ValueRepr::String(GcStr::from_utf8_unchecked(
                            context.alloc_ignore_limit(fmt.as_bytes()),
                        ))
                    };
                    context.stack.push(result);
                    Status::Error
                }
            }
        }
        _ => unreachable!(),
    }
}

extern "C" fn yield_(_vm: &Thread) -> Status {
    Status::Yield
}

fn spawn<'vm>(
    value: WithVM<'vm, Function<&'vm Thread, fn(())>>,
) -> RuntimeResult<RootedThread, Error> {
    spawn_(value).into()
}
fn spawn_<'vm>(value: WithVM<'vm, Function<&'vm Thread, fn(())>>) -> VmResult<RootedThread> {
    let thread = value.vm.new_thread()?;
    {
        let mut context = thread.context();
        let callable = match value.value.get_variant().0 {
            ValueRepr::Closure(c) => State::Closure(c),
            ValueRepr::Function(c) => State::Extern(c),
            _ => State::Unknown,
        };
        value.value.push(value.vm, &mut context)?;
        context.stack.push(ValueRepr::Int(0));
        StackFrame::current(&mut context.stack).enter_scope(1, callable);
    }
    Ok(thread)
}

type Action = fn(()) -> OpaqueValue<RootedThread, IO<Generic<A>>>;

#[cfg(target_arch = "wasm32")]
fn spawn_on<'vm>(
    _thread: RootedThread,
    _action: WithVM<'vm, FunctionRef<Action>>,
) -> IO<OpaqueValue<&'vm Thread, IO<Generic<A>>>> {
    IO::Exception("spawn_on requires the `tokio` crate".to_string())
}

#[cfg(not(target_arch = "wasm32"))]
fn spawn_on<'vm>(
    thread: RootedThread,
    action: WithVM<'vm, FunctionRef<Action>>,
) -> IO<OpaqueValue<&'vm Thread, IO<Generic<A>>>> {
    struct SpawnFuture<F>(future::Shared<F>)
    where
        F: Future;

    impl<F> fmt::Debug for SpawnFuture<F>
    where
        F: Future,
    {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "Future")
        }
    }

    impl<F> Userdata for SpawnFuture<F>
    where
        F: Future + Send + 'static,
        F::Item: Send + Sync,
        F::Error: Send + Sync,
    {}

    impl<F> Traverseable for SpawnFuture<F>
    where
        F: Future,
    {
        fn traverse(&self, _: &mut Gc) {}
    }

    impl<F> VmType for SpawnFuture<F>
    where
        F: Future,
    {
        type Type = Generic<A>;
    }

    fn push_future_wrapper<G>(vm: &Thread, context: &mut OwnedContext, _: &G)
    where
        G: Future<Item = OpaqueValue<RootedThread, IO<Generic<A>>>, Error = Error> + Send + 'static,
    {
        extern "C" fn future_wrapper<F>(vm: &Thread) -> Status
        where
            F: Future<Item = OpaqueValue<RootedThread, IO<Generic<A>>>, Error = Error>
                + Send
                + 'static,
        {
            let mut context = vm.context();
            let value = StackFrame::current(&mut context.stack)[0].get_repr();

            match value {
                ValueRepr::Userdata(data) => {
                    let data = data.downcast_ref::<SpawnFuture<F>>().unwrap();
                    let future = data.0.clone();
                    let lock = StackFrame::current(&mut context.stack).insert_lock();
                    AsyncPushable::async_status_push(
                        FutureResult::new(
                            future.map(|v| (*v).clone()).map_err(|err| (*err).clone()),
                        ),
                        vm,
                        &mut context,
                        lock,
                    )
                }
                _ => unreachable!(),
            }
        }

        type FutureArg = ();
        primitive::<fn(FutureArg) -> IO<Generic<A>>>("unknown", future_wrapper::<G>)
            .push(vm, context)
            .unwrap();
    }
    use value::PartialApplicationDataDef;

    let WithVM { vm, value: action } = action;
    let mut action = OwnedFunction::<Action>::from_value(&thread, action.get_variant());

    let future = future::lazy(move || action.call_async(()));

    let mut context = vm.context();

    push_future_wrapper(vm, &mut context, &future);

    let callable = match context.stack[context.stack.len() - 1].get_repr() {
        ValueRepr::Function(ext) => Callable::Extern(ext),
        _ => unreachable!(),
    };

    SpawnFuture(future.shared()).push(vm, &mut context).unwrap();
    let fields = [context.stack.get_values().last().unwrap().clone()];
    let def = PartialApplicationDataDef(callable, &fields);
    let value = ValueRepr::PartialApplication(context.alloc_with(vm, def).unwrap()).into();

    context.stack.pop_many(2);

    // TODO Remove rooting here
    IO::Value(OpaqueValue::from_value(vm.root_value(value)))
}

fn new_thread(WithVM { vm, .. }: WithVM<()>) -> IO<RootedThread> {
    match vm.new_thread() {
        Ok(thread) => IO::Value(thread),
        Err(err) => IO::Exception(err.to_string()),
    }
}

fn sleep(ms: VmInt) -> IO<()> {
    use std::time::Duration;
    ::std::thread::sleep(Duration::from_millis(ms as u64));
    IO::Value(())
}

fn interrupt(thread: RootedThread) -> IO<()> {
    thread.interrupt();
    IO::Value(())
}

mod std {
    pub use channel;
    pub mod thread {
        pub use channel as prim;
    }
}

pub fn load_channel<'vm>(vm: &'vm Thread) -> VmResult<ExternModule> {
    let _ = vm.register_type::<Sender<A>>("Sender", &["a"]);
    let _ = vm.register_type::<Receiver<A>>("Receiver", &["a"]);

    ExternModule::new(
        vm,
        record!{
            type Sender a => Sender<A>,
            type Receiver a => Sender<A>,
            channel => primitive!(1 std::channel::channel),
            recv => primitive!(1 std::channel::recv),
            send => primitive!(2 std::channel::send),
        },
    )
}

pub fn load_thread<'vm>(vm: &'vm Thread) -> VmResult<ExternModule> {
    ExternModule::new(
        vm,
        record!{
            resume => primitive::<fn(&'vm Thread) -> Result<(), String>>("std.thread.prim.resume", resume),
            (yield_ "yield") => primitive::<fn(())>("std.thread.prim.yield", yield_),
            spawn => primitive!(1 std::thread::prim::spawn),
            spawn_on => primitive!(2 std::thread::prim::spawn_on),
            new_thread => primitive!(1 std::thread::prim::new_thread),
            interrupt => primitive!(1 std::thread::prim::interrupt),
            sleep => primitive!(1 std::thread::prim::sleep)
        },
    )
}
<|endoftext|>


<commit_before>use std::fmt;

use serde::de;
use serde::de::{Deserialize, Deserializer, Visitor};

use types::*;

/// The member's status in the chat
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub enum ChatMemberStatus {
    Creator,
    Administrator,
    Member,
    Left,
    Kicked,
    #[doc(hidden)]
    Unknown(String),
}

impl<'de> Deserialize<'de> for ChatMemberStatus {
    fn deserialize<D>(deserializer: D) -> Result<ChatMemberStatus, D::Error>
        where D: Deserializer<'de>
    {
        struct ChatMemberStatusVisitor;
        use self::ChatMemberStatus::*;

        impl<'de> Visitor<'de> for ChatMemberStatusVisitor {
            type Value = ChatMemberStatus;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("creator | administrator | member | left | kicked")
            }

            fn visit_str<E>(self, value: &str) -> Result<ChatMemberStatus, E>
                where E: de::Error
            {
                Ok(match value {
                    "creator" => Creator,
                    "administrator" => Administrator,
                    "member" => Member,
                    "left" => Left,
                    "kicked" => Kicked,
                    _unknown => Unknown(value.to_string()),
                })
            }
        }

        deserializer.deserialize_str(ChatMemberStatusVisitor)
    }
}

/// This object contains information about one member of the chat.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct ChatMember {
    /// Information about the user.
    pub user: User,
    /// The member's status in the chat.
    pub status: ChatMemberStatus,
}
<commit_msg>Added missing fields for ChatMember<commit_after>use std::fmt;

use serde::de;
use serde::de::{Deserialize, Deserializer, Visitor};

use types::*;

/// The member's status in the chat
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub enum ChatMemberStatus {
    Creator,
    Administrator,
    Member,
    Left,
    Kicked,
    #[doc(hidden)]
    Unknown(String),
}

impl<'de> Deserialize<'de> for ChatMemberStatus {
    fn deserialize<D>(deserializer: D) -> Result<ChatMemberStatus, D::Error>
        where D: Deserializer<'de>
    {
        struct ChatMemberStatusVisitor;
        use self::ChatMemberStatus::*;

        impl<'de> Visitor<'de> for ChatMemberStatusVisitor {
            type Value = ChatMemberStatus;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("creator | administrator | member | left | kicked")
            }

            fn visit_str<E>(self, value: &str) -> Result<ChatMemberStatus, E>
                where E: de::Error
            {
                Ok(match value {
                    "creator" => Creator,
                    "administrator" => Administrator,
                    "member" => Member,
                    "left" => Left,
                    "kicked" => Kicked,
                    _unknown => Unknown(value.to_string()),
                })
            }
        }

        deserializer.deserialize_str(ChatMemberStatusVisitor)
    }
}

/// This object contains information about one member of the chat.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct ChatMember {
    /// Information about the user.
    pub user: User,
    /// The member's status in the chat.
    pub status: ChatMemberStatus,
    ///Optional. Restricted and kicked only. Date when restrictions will be lifted for this user, unix time
    pub until_date: Option<Integer>,
    ///Optional. Administrators only. True, if the bot is allowed to edit administrator privileges of that user
    pub can_be_edited: Option<bool>,
    ///Optional. Administrators only. True, if the administrator can change the chat title, photo and other settings
    pub can_change_info: Option<bool>,
    ///Optional. Administrators only. True, if the administrator can post in the channel, channels only
    pub can_post_messages: Option<bool>,
    ///Optional. Administrators only. True, if the administrator can edit messages of other users and can pin messages, channels only
    pub can_edit_messages: Option<bool>,
    ///Optional. Administrators only. True, if the administrator can delete messages of other users
    pub can_delete_messages: Option<bool>,
    ///Optional. Administrators only. True, if the administrator can invite new users to the chat
    pub can_invite_users: Option<bool>,
    ///Optional. Administrators only. True, if the administrator can restrict, ban or unban chat members
    pub can_restrict_members: Option<bool>,
    ///Optional. Administrators only. True, if the administrator can pin messages, supergroups only
    pub can_pin_messages: Option<bool>,
    ///Optional. Administrators only. True, if the administrator can add new administrators with a subset of his own privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by the user)
    pub can_promote_members: Option<bool>,
    ///Optional. Restricted only. True, if the user can send text messages, contacts, locations and venues
    pub can_send_messages: Option<bool>,
    ///Optional. Restricted only. True, if the user can send audios, documents, photos, videos, video notes and voice notes, implies can_send_messages
    pub can_send_media_messages: Option<bool>,
    ///Optional. Restricted only. True, if the user can send animations, games, stickers and use inline bots, implies can_send_media_messages
    pub can_send_other_messages: Option<bool>,
    ///Optional. Restricted only. True, if user may add web page previews to his messages, implies can_send_media_messages
    pub can_add_web_page_previews: Option<bool>,
}
<|endoftext|>


<commit_before>pub use core::libc::*;
pub use core::libc::types::os::arch::extra::*;

pub type PVOID = *c_void;
pub type HANDLE = PVOID;
pub type HWND = HANDLE;
pub type HMENU = HANDLE;
pub type HINSTANCE = HANDLE;
pub type UINT = c_uint;

pub extern "stdcall" mod user32 {
    unsafe fn MessageBoxW(hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR,
            uType: UINT) -> c_int;
}
<commit_msg>ll: add RegisterClass/CreateWindowEx/DefWindowProc<commit_after>pub use core::libc::*;
pub use core::libc::types::os::arch::extra::*;

pub type ATOM = WORD;
pub type UINT = c_uint;

// 32-bit specific
pub type UINT_PTR = c_uint;
pub type LONG_PTR = c_long;

pub type HANDLE = PVOID;

pub type HBRUSH = HANDLE;
pub type HCURSOR = HICON;
pub type HMENU = HANDLE;
pub type HICON = HANDLE;
pub type HINSTANCE = HANDLE;
pub type HWND = HANDLE;

pub type WPARAM = UINT_PTR;
pub type LPARAM = LONG_PTR;

pub type PVOID = *c_void;

// extern fn(HWND, UINT, WPARAM, LPARAM) -> LRESULT
pub type WNDPROC = *u8;

pub struct WNDCLASSEX {
    cbSize: UINT,
    style: UINT,
    lpfnWndProc: WNDPROC,
    cbClsExtra: c_int,
    cbWndExtra: c_int,
    hInstance: HINSTANCE,
    hIcon: HICON,
    hCursor: HCURSOR,
    hbrBackground: HBRUSH,
    lpszMenuName: LPCWSTR,
    lpszClassName: LPCWSTR,
    hIconSm: HICON,
}

pub extern "stdcall" mod user32 {
    unsafe fn CreateWindowExW(extrastyle: DWORD, classname: LPCWSTR,
            windowname: LPCWSTR, style: DWORD,
            x: c_int, y: c_int, width: c_int, height: c_int,
            parent: HWND, menu: HMENU, instance: HINSTANCE, param: LPVOID
    ) -> HWND;

    unsafe fn MessageBoxW(
            hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT
    ) -> c_int;

    unsafe fn RegisterClassExW(lpwcx: *WNDCLASSEX) -> ATOM;

    unsafe fn DefWindowProcW(
            hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM
    ) -> LRESULT;
}
<|endoftext|>