<commit_before>#![crate_name = "bindgen"]
#![crate_type = "bin"]

extern crate bindgen;
#[macro_use]
extern crate docopt;
#[macro_use]
extern crate log;
extern crate clang_sys;
extern crate rustc_serialize;

use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
use std::io;
use std::path;
use std::env;
use std::default::Default;
use std::fs;
use std::process::exit;

struct StdLogger;

impl Logger for StdLogger {
    fn error(&self, msg: &str) {
        println!("{}", msg);
    }

    fn warn(&self, msg: &str) {
        println!("{}", msg);
    }
}

const USAGE: &'static str = "
Usage:
    bindgen [options] \
        [--link=<lib>...] \
        [--static-link=<lib>...] \
        [--framework-link=<framework>...] \
        [--match=<name>...] \
        [--raw-line=<raw>...] \
        [--dtor-attr=<attr>...] \
        [--opaque-type=<type>...] \
        [--blacklist-type=<type>...] \
        <input-header> \
        [-- <clang-args>...]

    bindgen (-h | --help)

Options:
    -h, --help                    Display this help message.

    -l=<lib>, --link=<lib>        Link to a dynamic library, can be provided
                                  multiple times.

    --static-link=<lib>           Link to a static library, can be provided
                                  multiple times.

    --framework-link=<framework>  Link to a framework.

    -o=<output-rust-file>         Write bindings to <output-rust-file>
                                  (defaults to stdout)

    --match=<name>                Only output bindings for definitions from
                                  files whose name contains <name>. If multiple
                                  match options are provided, files matching any
                                  rule are bound to.

    --builtins                    Output bindings for builtin definitions (for
                                  example __builtin_va_list)

    --ignore-functions            Don't generate bindings for functions and
                                  methods. This is useful when you only care
                                  about struct layouts.

    --enable-cxx-namespaces       Enable support for C++ namespaces.

    --no-type-renaming            Don't rename types.

    --allow-unknown-types         Don't fail if we encounter types we do not
                                  support, instead treat them as void

    --emit-clang-ast              Output the ast (for debugging purposes)

    --use-msvc-mangling           Handle MSVC C++ ABI mangling; requires that
                                  target be set to (i686|x86_64)-pc-win32

    --override-enum-type=<type>   Override enum type, type name could be
                                    uchar
                                    schar
                                    ushort
                                    sshort
                                    uint
                                    sint
                                    ulong
                                    slong
                                    ulonglong
                                    slonglong

    --raw-line=<raw>              TODO
    --dtor-attr=<attr>            TODO
    --no-class-constants          TODO
    --no-unstable-rust            TODO
    --no-namespaced-constants     TODO
    --no-bitfield-methods         TODO
    --ignore-methods              TODO
    --opaque-type=<type>          TODO
    --blacklist-type=<type>       TODO

    <clang-args>                  Options other than stated above are passed
                                  directly through to clang.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_input_header: String,
    flag_link: Vec<String>,
    flag_static_link: Vec<String>,
    flag_framework_link: Vec<String>,
    flag_o: Option<String>,
    flag_match: Vec<String>,
    flag_builtins: bool,
    flag_ignore_functions: bool,
    flag_enable_cxx_namespaces: bool,
    flag_no_type_renaming: bool,
    flag_allow_unknown_types: bool,
    flag_emit_clang_ast: bool,
    flag_use_msvc_mangling: bool,
    flag_override_enum_type: String,
    flag_raw_line: Vec<String>,
    flag_dtor_attr: Vec<String>,
    flag_no_class_constants: bool,
    flag_no_unstable_rust: bool,
    flag_no_namespaced_constants: bool,
    flag_no_bitfield_methods: bool,
    flag_ignore_methods: bool,
    flag_opaque_type: Vec<String>,
    flag_blacklist_type: Vec<String>,
    arg_clang_args: Vec<String>,
}

type ParseResult<T> = Result<T, String>;

impl Into<ParseResult<(BindgenOptions, Box<io::Write>)>> for Args {
    fn into(mut self) -> Result<(BindgenOptions, Box<io::Write>), String> {
        let mut options: BindgenOptions = Default::default();

        options.clang_args.push(self.arg_input_header);

        for lib in self.flag_link.drain(..) {
            options.links.push((lib, LinkType::Default));
        }

        for lib in self.flag_static_link.drain(..) {
            options.links.push((lib, LinkType::Static));
        }

        for lib in self.flag_framework_link.drain(..) {
            options.links.push((lib, LinkType::Framework));
        }

        let out = if let Some(ref path_name) = self.flag_o {
            let path = path::Path::new(path_name);
            let file = try!(fs::File::create(path).map_err(|_| {
                format!("Opening {} failed", path_name)
            }));
            Box::new(io::BufWriter::new(file)) as Box<io::Write>
        } else {
            Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
        };

        options.match_pat.extend(self.flag_match.drain(..));
        options.builtins = self.flag_builtins;
        options.ignore_functions = self.flag_ignore_functions;
        options.enable_cxx_namespaces = self.flag_enable_cxx_namespaces;
        options.rename_types = !self.flag_no_type_renaming;
        options.fail_on_unknown_type = !self.flag_allow_unknown_types;
        options.emit_ast = self.flag_emit_clang_ast;
        options.msvc_mangling = self.flag_use_msvc_mangling;
        options.override_enum_ty = self.flag_override_enum_type;
        options.raw_lines.extend(self.flag_raw_line.drain(..));
        options.dtor_attrs.extend(self.flag_dtor_attr.drain(..));
        options.class_constants = !self.flag_no_class_constants;
        options.unstable_rust = !self.flag_no_unstable_rust;
        options.namespaced_constants = !self.flag_no_namespaced_constants;
        options.gen_bitfield_methods = !self.flag_no_bitfield_methods;
        options.ignore_methods = self.flag_ignore_methods;
        options.opaque_types.extend(self.flag_opaque_type.drain(..));
        options.blacklist_type.extend(self.flag_blacklist_type.drain(..));
        options.clang_args.extend(self.arg_clang_args.drain(..));

        Ok((options, out))
    }
}

pub fn main() {
    let mut bind_args: Vec<_> = env::args().collect();

    if let Some(clang) = clang_sys::support::Clang::find(None) {
        let has_clang_args = bind_args.iter().rposition(|arg| *arg == "--").is_some();
        if !has_clang_args {
            bind_args.push("--".to_owned());
        }

        // TODO: distinguish C and C++ paths? C++'s should be enough, I guess.
        for path in clang.cpp_search_paths.into_iter() {
            if let Ok(path) = path.into_os_string().into_string() {
                bind_args.push("-isystem".to_owned());
                bind_args.push(path);
            }
        }
    }

    let args: Args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.argv(bind_args.iter()).decode())
        .unwrap_or_else(|e| e.exit());

    let logger = StdLogger;
    let result: ParseResult<_> = args.into();
    let (options, out) = result.unwrap_or_else(|msg| {
        logger.error(&msg);
        exit(-1);
    });

    match Bindings::generate(&options, Some(&logger as &Logger), None) {
        Ok(bindings) => match bindings.write(out) {
            Ok(()) => (),
            Err(e) => {
                logger.error(&format!("Unable to write bindings to file. {}", e));
                exit(-1);
            }
        },
        Err(()) => {
            logger.error("Failed to generate bindings".into());
            exit(-1);
        }
    }
}
<commit_msg>Auto merge of #45 - fitzgen:use-docopt-for-args, r=emilio<commit_after>#![crate_name = "bindgen"]
#![crate_type = "bin"]

extern crate bindgen;
#[macro_use]
extern crate docopt;
#[macro_use]
extern crate log;
extern crate clang_sys;
extern crate rustc_serialize;

use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
use std::io;
use std::path;
use std::env;
use std::default::Default;
use std::fs;
use std::process::exit;

struct StdLogger;

impl Logger for StdLogger {
    fn error(&self, msg: &str) {
        println!("{}", msg);
    }

    fn warn(&self, msg: &str) {
        println!("{}", msg);
    }
}

const USAGE: &'static str = "
Usage:
    bindgen [options] \
        [--link=<lib>...] \
        [--static-link=<lib>...] \
        [--framework-link=<framework>...] \
        [--match=<name>...] \
        [--raw-line=<raw>...] \
        [--dtor-attr=<attr>...] \
        [--opaque-type=<type>...] \
        [--blacklist-type=<type>...] \
        <input-header> \
        [-- <clang-args>...]

    bindgen (-h | --help)

Options:
    -h, --help                    Display this help message.

    -l=<lib>, --link=<lib>        Link to a dynamic library, can be provided
                                  multiple times.

    --static-link=<lib>           Link to a static library, can be provided
                                  multiple times.

    --framework-link=<framework>  Link to a framework.

    -o=<output-rust-file>         Write bindings to <output-rust-file>
                                  (defaults to stdout)

    --match=<name>                Only output bindings for definitions from
                                  files whose name contains <name>. If multiple
                                  match options are provided, files matching any
                                  rule are bound to.

    --builtins                    Output bindings for builtin definitions (for
                                  example __builtin_va_list)

    --ignore-functions            Don't generate bindings for functions and
                                  methods. This is useful when you only care
                                  about struct layouts.

    --enable-cxx-namespaces       Enable support for C++ namespaces.

    --no-type-renaming            Don't rename types.

    --allow-unknown-types         Don't fail if we encounter types we do not
                                  support, instead treat them as void

    --emit-clang-ast              Output the ast (for debugging purposes)

    --use-msvc-mangling           Handle MSVC C++ ABI mangling; requires that
                                  target be set to (i686|x86_64)-pc-win32

    --override-enum-type=<type>   Override enum type, type name could be
                                    uchar
                                    schar
                                    ushort
                                    sshort
                                    uint
                                    sint
                                    ulong
                                    slong
                                    ulonglong
                                    slonglong

    --raw-line=<raw>              TODO
    --dtor-attr=<attr>            TODO
    --no-class-constants          TODO
    --no-unstable-rust            TODO
    --no-namespaced-constants     TODO
    --no-bitfield-methods         TODO
    --ignore-methods              TODO
    --opaque-type=<type>          TODO
    --blacklist-type=<type>       TODO

    <clang-args>                  Options other than stated above are passed
                                  directly through to clang.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_input_header: String,
    flag_link: Vec<String>,
    flag_static_link: Vec<String>,
    flag_framework_link: Vec<String>,
    flag_o: Option<String>,
    flag_match: Vec<String>,
    flag_builtins: bool,
    flag_ignore_functions: bool,
    flag_enable_cxx_namespaces: bool,
    flag_no_type_renaming: bool,
    flag_allow_unknown_types: bool,
    flag_emit_clang_ast: bool,
    flag_use_msvc_mangling: bool,
    flag_override_enum_type: String,
    flag_raw_line: Vec<String>,
    flag_dtor_attr: Vec<String>,
    flag_no_class_constants: bool,
    flag_no_unstable_rust: bool,
    flag_no_namespaced_constants: bool,
    flag_no_bitfield_methods: bool,
    flag_ignore_methods: bool,
    flag_opaque_type: Vec<String>,
    flag_blacklist_type: Vec<String>,
    arg_clang_args: Vec<String>,
}

type ParseResult<T> = Result<T, String>;

impl Into<ParseResult<(BindgenOptions, Box<io::Write>)>> for Args {
    fn into(mut self) -> Result<(BindgenOptions, Box<io::Write>), String> {
        let mut options: BindgenOptions = Default::default();

        for lib in self.flag_link.drain(..) {
            options.links.push((lib, LinkType::Default));
        }

        for lib in self.flag_static_link.drain(..) {
            options.links.push((lib, LinkType::Static));
        }

        for lib in self.flag_framework_link.drain(..) {
            options.links.push((lib, LinkType::Framework));
        }

        let out = if let Some(ref path_name) = self.flag_o {
            let path = path::Path::new(path_name);
            let file = try!(fs::File::create(path).map_err(|_| {
                format!("Opening {} failed", path_name)
            }));
            Box::new(io::BufWriter::new(file)) as Box<io::Write>
        } else {
            Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
        };

        options.match_pat.extend(self.flag_match.drain(..));
        options.builtins = self.flag_builtins;
        options.ignore_functions = self.flag_ignore_functions;
        options.enable_cxx_namespaces = self.flag_enable_cxx_namespaces;
        options.rename_types = !self.flag_no_type_renaming;
        options.fail_on_unknown_type = !self.flag_allow_unknown_types;
        options.emit_ast = self.flag_emit_clang_ast;
        options.msvc_mangling = self.flag_use_msvc_mangling;
        options.override_enum_ty = self.flag_override_enum_type;
        options.raw_lines.extend(self.flag_raw_line.drain(..));
        options.dtor_attrs.extend(self.flag_dtor_attr.drain(..));
        options.class_constants = !self.flag_no_class_constants;
        options.unstable_rust = !self.flag_no_unstable_rust;
        options.namespaced_constants = !self.flag_no_namespaced_constants;
        options.gen_bitfield_methods = !self.flag_no_bitfield_methods;
        options.ignore_methods = self.flag_ignore_methods;
        options.opaque_types.extend(self.flag_opaque_type.drain(..));
        options.blacklist_type.extend(self.flag_blacklist_type.drain(..));
        options.clang_args.extend(self.arg_clang_args.drain(..));
        options.clang_args.push(self.arg_input_header);

        Ok((options, out))
    }
}

pub fn main() {
    let mut bind_args: Vec<_> = env::args().collect();

    if let Some(clang) = clang_sys::support::Clang::find(None) {
        let has_clang_args = bind_args.iter().rposition(|arg| *arg == "--").is_some();
        if !has_clang_args {
            bind_args.push("--".to_owned());
        }

        // TODO: distinguish C and C++ paths? C++'s should be enough, I guess.
        for path in clang.cpp_search_paths.into_iter() {
            if let Ok(path) = path.into_os_string().into_string() {
                bind_args.push("-isystem".to_owned());
                bind_args.push(path);
            }
        }
    }

    let args: Args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.argv(bind_args.iter()).decode())
        .unwrap_or_else(|e| e.exit());

    let logger = StdLogger;
    let result: ParseResult<_> = args.into();
    let (options, out) = result.unwrap_or_else(|msg| {
        logger.error(&msg);
        exit(-1);
    });

    match Bindings::generate(&options, Some(&logger as &Logger), None) {
        Ok(bindings) => match bindings.write(out) {
            Ok(()) => (),
            Err(e) => {
                logger.error(&format!("Unable to write bindings to file. {}", e));
                exit(-1);
            }
        },
        Err(()) => {
            logger.error("Failed to generate bindings".into());
            exit(-1);
        }
    }
}
<|endoftext|>


<commit_before>extern crate jpeg_decoder as jpeg;
extern crate png;

use std::env;
use std::fs::File;
use std::io::{self, BufReader, Write};
use std::process;

fn usage() -> ! {
    write!(io::stderr(), "usage: decode image.jpg image.png").unwrap();
    process::exit(1)
}

fn main() {
    let mut args = env::args().skip(1);
    let input_path = args.next().unwrap_or_else(|| usage());
    let output_path = args.next().unwrap_or_else(|| usage());

    let input_file = File::open(input_path).expect("The specified input file could not be opened");
    let mut decoder = jpeg::Decoder::new(BufReader::new(input_file));
    let mut data = decoder.decode().expect("Decoding failed. If other software can successfully decode the specified JPEG image, then it's likely that there is a bug in jpeg-decoder");
    let info = decoder.info().unwrap();

    let output_file = File::create(output_path).unwrap();
    let mut encoder = png::Encoder::new(output_file, info.width as u32, info.height as u32);

    match info.pixel_format {
        jpeg::PixelFormat::L16 => {
            encoder.set_depth(png::BitDepth::Sixteen);
            encoder.set_color(png::ColorType::Grayscale);
        },
        jpeg::PixelFormat::RGB24  => {
            encoder.set_depth(png::BitDepth::Eight);
            encoder.set_color(png::ColorType::RGB);
        },
        jpeg::PixelFormat::CMYK32 => {
            data = cmyk_to_rgb(&mut data);
            encoder.set_depth(png::BitDepth::Eight);
            encoder.set_color(png::ColorType::RGB)
        },
        jpeg::PixelFormat::L8 => {
            encoder.set_depth(png::BitDepth::Eight);
            encoder.set_color(png::ColorType::Grayscale);
        },
    }

    encoder.write_header()
           .expect("writing png header failed")
           .write_image_data(&data)
           .expect("png encoding failed");
}

fn cmyk_to_rgb(input: &[u8]) -> Vec<u8> {
    let size = input.len() - input.len() / 4;
    let mut output = Vec::with_capacity(size);

    for pixel in input.chunks(4) {
        let c = pixel[0] as f32 / 255.0;
        let m = pixel[1] as f32 / 255.0;
        let y = pixel[2] as f32 / 255.0;
        let k = pixel[3] as f32 / 255.0;

        // CMYK -> CMY
        let c = c * (1.0 - k) + k;
        let m = m * (1.0 - k) + k;
        let y = y * (1.0 - k) + k;

        // CMY -> RGB
        let r = (1.0 - c) * 255.0;
        let g = (1.0 - m) * 255.0;
        let b = (1.0 - y) * 255.0;

        output.push(r as u8);
        output.push(g as u8);
        output.push(b as u8);
    }

    output
}
<commit_msg>Print Exif, Icc available in decode example<commit_after>extern crate jpeg_decoder as jpeg;
extern crate png;

use std::env;
use std::fs::File;
use std::io::{self, BufReader, Write};
use std::process;

fn usage() -> ! {
    write!(io::stderr(), "usage: decode image.jpg image.png").unwrap();
    process::exit(1)
}

fn main() {
    let mut args = env::args().skip(1);
    let input_path = args.next().unwrap_or_else(|| usage());
    let output_path = args.next().unwrap_or_else(|| usage());

    let input_file = File::open(input_path).expect("The specified input file could not be opened");
    let mut decoder = jpeg::Decoder::new(BufReader::new(input_file));
    let mut data = decoder.decode().expect("Decoding failed. If other software can successfully decode the specified JPEG image, then it's likely that there is a bug in jpeg-decoder");
    let info = decoder.info().unwrap();

    eprintln!("{:?}", info);
    eprintln!("Exif: {}", decoder.exif_data().is_some());
    eprintln!("ICC: {}", decoder.icc_profile().is_some());

    let output_file = File::create(output_path).unwrap();
    let mut encoder = png::Encoder::new(output_file, info.width as u32, info.height as u32);

    match info.pixel_format {
        jpeg::PixelFormat::L16 => {
            encoder.set_depth(png::BitDepth::Sixteen);
            encoder.set_color(png::ColorType::Grayscale);
        },
        jpeg::PixelFormat::RGB24  => {
            encoder.set_depth(png::BitDepth::Eight);
            encoder.set_color(png::ColorType::RGB);
        },
        jpeg::PixelFormat::CMYK32 => {
            data = cmyk_to_rgb(&mut data);
            encoder.set_depth(png::BitDepth::Eight);
            encoder.set_color(png::ColorType::RGB)
        },
        jpeg::PixelFormat::L8 => {
            encoder.set_depth(png::BitDepth::Eight);
            encoder.set_color(png::ColorType::Grayscale);
        },
    }

    encoder.write_header()
           .expect("writing png header failed")
           .write_image_data(&data)
           .expect("png encoding failed");
}

fn cmyk_to_rgb(input: &[u8]) -> Vec<u8> {
    let size = input.len() - input.len() / 4;
    let mut output = Vec::with_capacity(size);

    for pixel in input.chunks(4) {
        let c = pixel[0] as f32 / 255.0;
        let m = pixel[1] as f32 / 255.0;
        let y = pixel[2] as f32 / 255.0;
        let k = pixel[3] as f32 / 255.0;

        // CMYK -> CMY
        let c = c * (1.0 - k) + k;
        let m = m * (1.0 - k) + k;
        let y = y * (1.0 - k) + k;

        // CMY -> RGB
        let r = (1.0 - c) * 255.0;
        let g = (1.0 - m) * 255.0;
        let b = (1.0 - y) * 255.0;

        output.push(r as u8);
        output.push(g as u8);
        output.push(b as u8);
    }

    output
}
<|endoftext|>


<commit_before>// #![deny(warnings)]  // FIXME: https://github.com/rust-lang/rust/issues/62411
#![warn(rust_2018_idioms)]

use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Method, Request, Response, Server, StatusCode};

use std::collections::HashMap;
use url::form_urlencoded;

static INDEX: &[u8] = b"<form action=\"post\" method=\"post\">Name: <input type=\"text\" name=\"name\">
Number: <input type=\"text\" name=\"number\">
<input type=\"submit\">";
static MISSING: &[u8] = b"Missing field";
static NOTNUMERIC: &[u8] = b"Number field is not numeric";

// Using service_fn, we can turn this function into a `Service`.
async fn param_example(req: Request) -> Result<Response, hyper::Error> {
    match (req.method(), req.uri().path()) {
        (&Method::GET, "/") | (&Method::GET, "/post") => Ok(Response::new(INDEX.into())),
        (&Method::POST, "/post") => {
            // Concatenate the body...
            let b = hyper::body::to_bytes(req).await?;
            // Parse the request body. form_urlencoded::parse
            // always succeeds, but in general parsing may
            // fail (for example, an invalid post of json), so
            // returning early with BadRequest may be
            // necessary.
            //
            // Warning: this is a simplified use case. In
            // principle names can appear multiple times in a
            // form, and the values should be rolled up into a
            // HashMap<String, Vec<String>>. However in this
            // example the simpler approach is sufficient.
            let params = form_urlencoded::parse(b.as_ref())
                .into_owned()
                .collect::<HashMap<String, String>>();

            // Validate the request parameters, returning
            // early if an invalid input is detected.
            let name = if let Some(n) = params.get("name") {
                n
            } else {
                return Ok(Response::builder()
                    .status(StatusCode::UNPROCESSABLE_ENTITY)
                    .body(MISSING.into())
                    .unwrap());
            };
            let number = if let Some(n) = params.get("number") {
                if let Ok(v) = n.parse::<f64>() {
                    v
                } else {
                    return Ok(Response::builder()
                        .status(StatusCode::UNPROCESSABLE_ENTITY)
                        .body(NOTNUMERIC.into())
                        .unwrap());
                }
            } else {
                return Ok(Response::builder()
                    .status(StatusCode::UNPROCESSABLE_ENTITY)
                    .body(MISSING.into())
                    .unwrap());
            };

            // Render the response. This will often involve
            // calls to a database or web service, which will
            // require creating a new stream for the response
            // body. Since those may fail, other error
            // responses such as InternalServiceError may be
            // needed here, too.
            let body = format!("Hello {}, your number is {}", name, number);
            Ok(Response::new(body.into()))
        }
        _ => Ok(Response::builder()
            .status(StatusCode::NOT_FOUND)
            .body(Body::empty())
            .unwrap()),
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    pretty_env_logger::init();

    let addr = ([127, 0, 0, 1], 1337).into();

    let server = Server::bind(&addr).serve(make_service_fn(|_| async {
        Ok::<_, hyper::Error>(service_fn(param_example))
    }));

    println!("Listening on http://{}", addr);

    server.await?;

    Ok(())
}
<commit_msg>docs(example): add a get query method to params example (#2601)<commit_after>// #![deny(warnings)]  // FIXME: https://github.com/rust-lang/rust/issues/62411
#![warn(rust_2018_idioms)]

use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Method, Request, Response, Server, StatusCode};

use std::collections::HashMap;
use url::form_urlencoded;

static INDEX: &[u8] = b"<form action=\"post\" method=\"post\">Name: <input type=\"text\" name=\"name\">
Number: <input type=\"text\" name=\"number\">
<input type=\"submit\">";
static MISSING: &[u8] = b"Missing field";
static NOTNUMERIC: &[u8] = b"Number field is not numeric";

// Using service_fn, we can turn this function into a `Service`.
async fn param_example(req: Request) -> Result<Response, hyper::Error> {
    match (req.method(), req.uri().path()) {
        (&Method::GET, "/") | (&Method::GET, "/post") => Ok(Response::new(INDEX.into())),
        (&Method::POST, "/post") => {
            // Concatenate the body...
            let b = hyper::body::to_bytes(req).await?;
            // Parse the request body. form_urlencoded::parse
            // always succeeds, but in general parsing may
            // fail (for example, an invalid post of json), so
            // returning early with BadRequest may be
            // necessary.
            //
            // Warning: this is a simplified use case. In
            // principle names can appear multiple times in a
            // form, and the values should be rolled up into a
            // HashMap<String, Vec<String>>. However in this
            // example the simpler approach is sufficient.
            let params = form_urlencoded::parse(b.as_ref())
                .into_owned()
                .collect::<HashMap<String, String>>();

            // Validate the request parameters, returning
            // early if an invalid input is detected.
            let name = if let Some(n) = params.get("name") {
                n
            } else {
                return Ok(Response::builder()
                    .status(StatusCode::UNPROCESSABLE_ENTITY)
                    .body(MISSING.into())
                    .unwrap());
            };
            let number = if let Some(n) = params.get("number") {
                if let Ok(v) = n.parse::<f64>() {
                    v
                } else {
                    return Ok(Response::builder()
                        .status(StatusCode::UNPROCESSABLE_ENTITY)
                        .body(NOTNUMERIC.into())
                        .unwrap());
                }
            } else {
                return Ok(Response::builder()
                    .status(StatusCode::UNPROCESSABLE_ENTITY)
                    .body(MISSING.into())
                    .unwrap());
            };

            // Render the response. This will often involve
            // calls to a database or web service, which will
            // require creating a new stream for the response
            // body. Since those may fail, other error
            // responses such as InternalServiceError may be
            // needed here, too.
            let body = format!("Hello {}, your number is {}", name, number);
            Ok(Response::new(body.into()))
        }
        (&Method::GET, "/get") => {
            let query = if let Some(q) = req.uri().query() {
                q
            } else {
                return Ok(Response::builder()
                    .status(StatusCode::UNPROCESSABLE_ENTITY)
                    .body(MISSING.into())
                    .unwrap());
            };
            let params = form_urlencoded::parse(query.as_bytes())
                .into_owned()
                .collect::<HashMap<String, String>>();
            let page = if let Some(p) = params.get("page") {
                p
            } else {
                return Ok(Response::builder()
                    .status(StatusCode::UNPROCESSABLE_ENTITY)
                    .body(MISSING.into())
                    .unwrap());
            };
            let body = format!("You requested {}", page);
            Ok(Response::new(body.into()))
        }
        _ => Ok(Response::builder()
            .status(StatusCode::NOT_FOUND)
            .body(Body::empty())
            .unwrap()),
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    pretty_env_logger::init();

    let addr = ([127, 0, 0, 1], 1337).into();

    let server = Server::bind(&addr).serve(make_service_fn(|_| async {
        Ok::<_, hyper::Error>(service_fn(param_example))
    }));

    println!("Listening on http://{}", addr);

    server.await?;

    Ok(())
}
<|endoftext|>


<commit_before>//! A chat server that broadcasts a message to all connections.
//!
//! This is a simple line-based server which accepts WebSocket connections,
//! reads lines from those connections, and broadcasts the lines to all other
//! connected clients.
//!
//! You can test this out by running:
//!
//!     cargo run --example server 127.0.0.1:12345
//!
//! And then in another window run:
//!
//!     cargo run --example client ws://127.0.0.1:12345/
//!
//! You can run the second command in multiple windows and then chat between the
//! two, seeing the messages from the other client as they're received. For all
//! connected clients they'll all join the same room and see everyone else's
//! messages.

use std::env;
use std::io::Error;

use std::sync::{Arc,Mutex};
use std::collections::HashMap;
use futures::channel::mpsc::UnboundedSender;
use futures::{SinkExt, StreamExt};
use futures::stream::SplitStream;
use log::*;
use std::net::{SocketAddr, ToSocketAddrs};
use tokio::net::{TcpListener, TcpStream};
use tungstenite::protocol::Message;

type Tx = UnboundedSender<Message>;

type WsRx = SplitStream<tokio_tungstenite::WebSocketStream<TcpStream>>;

type PeerMap = Arc<Mutex<HashMap<SocketAddr, Tx>>>;

async fn handle_message(addr: SocketAddr, peer_map: PeerMap, ws_rx: WsRx ) {
    let mut ws_rx = ws_rx;
    while let Some(msg) = ws_rx.next().await {
        let msg = msg.expect("Failed to get response");
        info!("Received a message from {}: {}", addr, msg.to_text().unwrap());

        for peer in peer_map.lock().unwrap().iter_mut() {
            let _ = peer.1.unbounded_send(msg.clone().into());
        }
    }
}

async fn accept_connection(peer_map: PeerMap, raw_stream: TcpStream) {
    let addr = raw_stream
        .peer_addr()
        .expect("connected streams should have a peer address");
    info!("Peer address: {}", addr);

    let ws_stream = tokio_tungstenite::accept_async(raw_stream)
        .await
        .expect("Error during the websocket handshake occurred");

    info!("New WebSocket connection: {}", addr);

    let (mut ws_tx, ws_rx) = ws_stream.split();
    let (msg_tx, mut msg_rx) = futures::channel::mpsc::unbounded();

    //We want to be able to send data to a specific peer, use this tx.
    peer_map.lock().unwrap().insert(addr, msg_tx);

    //Handle incoming messages
    tokio::spawn(handle_message(addr, peer_map.clone(), ws_rx));

    //If msg_rx get's some data, send it on the websocket.
    while let Some(msg) = msg_rx.next().await {
        info!("Sending message to {}", addr);
        ws_tx.send(msg).await.expect("Failed to send request");
    }
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let _ = env_logger::try_init();
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr
        .to_socket_addrs()
        .expect("Not a valid address")
        .next()
        .expect("Not a socket address");

    let hm: HashMap<SocketAddr,Tx> = HashMap::new();
    let state = PeerMap::new(Mutex::new(hm));

    // Create the event loop and TCP listener we'll accept connections on.
    let try_socket = TcpListener::bind(&addr).await;
    let mut listener = try_socket.expect("Failed to bind");
    info!("Listening on: {}", addr);

    while let Ok((stream, _)) = listener.accept().await {
        tokio::spawn(accept_connection(state.clone(), stream));
    }

    Ok(())
}

<commit_msg>Run `cargo fmt` over the new server example<commit_after>//! A chat server that broadcasts a message to all connections.
//!
//! This is a simple line-based server which accepts WebSocket connections,
//! reads lines from those connections, and broadcasts the lines to all other
//! connected clients.
//!
//! You can test this out by running:
//!
//!     cargo run --example server 127.0.0.1:12345
//!
//! And then in another window run:
//!
//!     cargo run --example client ws://127.0.0.1:12345/
//!
//! You can run the second command in multiple windows and then chat between the
//! two, seeing the messages from the other client as they're received. For all
//! connected clients they'll all join the same room and see everyone else's
//! messages.

use std::env;
use std::io::Error;

use futures::channel::mpsc::UnboundedSender;
use futures::stream::SplitStream;
use futures::{SinkExt, StreamExt};
use log::*;
use std::collections::HashMap;
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::{Arc, Mutex};
use tokio::net::{TcpListener, TcpStream};
use tungstenite::protocol::Message;

type Tx = UnboundedSender<Message>;

type WsRx = SplitStream<tokio_tungstenite::WebSocketStream<TcpStream>>;

type PeerMap = Arc<Mutex<HashMap<SocketAddr, Tx>>>;

async fn handle_message(addr: SocketAddr, peer_map: PeerMap, ws_rx: WsRx) {
    let mut ws_rx = ws_rx;
    while let Some(msg) = ws_rx.next().await {
        let msg = msg.expect("Failed to get response");
        info!(
            "Received a message from {}: {}",
            addr,
            msg.to_text().unwrap()
        );

        for peer in peer_map.lock().unwrap().iter_mut() {
            let _ = peer.1.unbounded_send(msg.clone().into());
        }
    }
}

async fn accept_connection(peer_map: PeerMap, raw_stream: TcpStream) {
    let addr = raw_stream
        .peer_addr()
        .expect("connected streams should have a peer address");
    info!("Peer address: {}", addr);

    let ws_stream = tokio_tungstenite::accept_async(raw_stream)
        .await
        .expect("Error during the websocket handshake occurred");

    info!("New WebSocket connection: {}", addr);

    let (mut ws_tx, ws_rx) = ws_stream.split();
    let (msg_tx, mut msg_rx) = futures::channel::mpsc::unbounded();

    //We want to be able to send data to a specific peer, use this tx.
    peer_map.lock().unwrap().insert(addr, msg_tx);

    //Handle incoming messages
    tokio::spawn(handle_message(addr, peer_map.clone(), ws_rx));

    //If msg_rx get's some data, send it on the websocket.
    while let Some(msg) = msg_rx.next().await {
        info!("Sending message to {}", addr);
        ws_tx.send(msg).await.expect("Failed to send request");
    }
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let _ = env_logger::try_init();
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr
        .to_socket_addrs()
        .expect("Not a valid address")
        .next()
        .expect("Not a socket address");

    let hm: HashMap<SocketAddr, Tx> = HashMap::new();
    let state = PeerMap::new(Mutex::new(hm));

    // Create the event loop and TCP listener we'll accept connections on.
    let try_socket = TcpListener::bind(&addr).await;
    let mut listener = try_socket.expect("Failed to bind");
    info!("Listening on: {}", addr);

    while let Ok((stream, _)) = listener.accept().await {
        tokio::spawn(accept_connection(state.clone(), stream));
    }

    Ok(())
}
<|endoftext|>


<commit_before>extern crate rusttype;

use rusttype::{FontCollection, Scale, point, PositionedGlyph};
use std::io::Write;

fn main() {
    let font_data = include_bytes!("Arial Unicode.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap(); // only succeeds if collection consists of one font

    // Desired font pixel height
    let height: f32 = 12.4; // to get 80 chars across (fits most terminals); adjust as desired
    let pixel_height = height.ceil() as usize;

    // 2x scale in x direction to counter the aspect ratio of monospace characters.
    let scale = Scale { x: height*2.0, y: height };

    // The origin of a line of text is at the baseline (roughly where non-descending letters sit).
    // We don't want to clip the text, so we shift it down with an offset when laying it out.
    // v_metrics.ascent is the distance between the baseline and the highest edge of any glyph in
    // the font. That's enough to guarantee that there's no clipping.
    let v_metrics = font.v_metrics(scale);
    let offset = point(0.0, v_metrics.ascent);

    // Glyphs to draw for "RustType". Feel free to try other strings.
    let glyphs: Vec<PositionedGlyph> = font.layout("RustType", scale, offset).collect();

    // Find the most visually pleasing width to display
    let width = glyphs.iter().rev()
        .filter_map(|g| g.pixel_bounding_box()
                    .map(|b| b.min.x as f32 + g.unpositioned().h_metrics().advance_width))
        .next().unwrap_or(0.0).ceil() as usize;

    println!("width: {}, height: {}", width, pixel_height);

    // Rasterise directly into ASCII art.
    let mut pixel_data = vec![b'@'; width * pixel_height];
    let mapping = b"@%#x+=:-. "; // The approximation of greyscale
    let mapping_scale = (mapping.len()-1) as f32;
    for g in glyphs {
        if let Some(bb) = g.pixel_bounding_box() {
            g.draw(|x, y, v| {
                // v should be in the range 0.0 to 1.0
                let i = (v*mapping_scale + 0.5) as usize;
                // so something's wrong if you get $ in the output.
                let c = mapping.get(i).cloned().unwrap_or(b'$');
                let x = x as i32 + bb.min.x;
                let y = y as i32 + bb.min.y;
                // There's still a possibility that the glyph clips the boundaries of the bitmap
                if x >= 0 && x < width as i32 && y >= 0 && y < pixel_height as i32 {
                    let x = x as usize;
                    let y = y as usize;
                    pixel_data[(x + y * width)] = c;
                }
            })
        }
    }

    // Print it out
    let stdout = ::std::io::stdout();
    let mut handle = stdout.lock();
    for j in 0..pixel_height {
        handle.write(&pixel_data[j*width..(j+1)*width]).unwrap();
        handle.write(b"\n").unwrap();
    }
}
<commit_msg>Use `position` instead of `pixel_bounding_box` for width calculation<commit_after>extern crate rusttype;

use rusttype::{FontCollection, Scale, point, PositionedGlyph};
use std::io::Write;

fn main() {
    let font_data = include_bytes!("Arial Unicode.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap(); // only succeeds if collection consists of one font

    // Desired font pixel height
    let height: f32 = 12.4; // to get 80 chars across (fits most terminals); adjust as desired
    let pixel_height = height.ceil() as usize;

    // 2x scale in x direction to counter the aspect ratio of monospace characters.
    let scale = Scale { x: height*2.0, y: height };

    // The origin of a line of text is at the baseline (roughly where non-descending letters sit).
    // We don't want to clip the text, so we shift it down with an offset when laying it out.
    // v_metrics.ascent is the distance between the baseline and the highest edge of any glyph in
    // the font. That's enough to guarantee that there's no clipping.
    let v_metrics = font.v_metrics(scale);
    let offset = point(0.0, v_metrics.ascent);

    // Glyphs to draw for "RustType". Feel free to try other strings.
    let glyphs: Vec<PositionedGlyph> = font.layout("RustType", scale, offset).collect();

    // Find the most visually pleasing width to display
    let width = glyphs.iter().rev()
        .map(|g| g.position().x as f32 + g.unpositioned().h_metrics().advance_width)
        .next().unwrap_or(0.0).ceil() as usize;

    println!("width: {}, height: {}", width, pixel_height);

    // Rasterise directly into ASCII art.
    let mut pixel_data = vec![b'@'; width * pixel_height];
    let mapping = b"@%#x+=:-. "; // The approximation of greyscale
    let mapping_scale = (mapping.len()-1) as f32;
    for g in glyphs {
        if let Some(bb) = g.pixel_bounding_box() {
            g.draw(|x, y, v| {
                // v should be in the range 0.0 to 1.0
                let i = (v*mapping_scale + 0.5) as usize;
                // so something's wrong if you get $ in the output.
                let c = mapping.get(i).cloned().unwrap_or(b'$');
                let x = x as i32 + bb.min.x;
                let y = y as i32 + bb.min.y;
                // There's still a possibility that the glyph clips the boundaries of the bitmap
                if x >= 0 && x < width as i32 && y >= 0 && y < pixel_height as i32 {
                    let x = x as usize;
                    let y = y as usize;
                    pixel_data[(x + y * width)] = c;
                }
            })
        }
    }

    // Print it out
    let stdout = ::std::io::stdout();
    let mut handle = stdout.lock();
    for j in 0..pixel_height {
        handle.write(&pixel_data[j*width..(j+1)*width]).unwrap();
        handle.write(b"\n").unwrap();
    }
}
<|endoftext|>


<commit_before>use luminance::{Depth32F, Dim2, Flat, Texture, RGBA32F};
use std::ops::{Add, Sub, Mul};

pub use luminance::{Equation, Factor};

/// Layer render that can be embedded into a compositing graph.
pub type LayerRender<'a> = (ColorMap<'a>, DepthMap<'a>);
/// Simple texture that can be embedded into a compositing graph.
pub type LayerTexture<'a> = ColorMap<'a>;

pub type ColorMap<'a> = &'a Texture<Flat, Dim2, RGBA32F>;
pub type DepthMap<'a> = &'a Texture<Flat, Dim2, Depth32F>;

/// Compositing node.
pub enum Node<'a> {
  /// A render node.
  ///
  /// Contains a color map and a depth map.
  Render(LayerRender<'a>),
  /// A texture node.
  ///
  /// Contains a single texture.
  Texture(LayerTexture<'a>),
  /// Composite node.
  ///
  /// Composite nodes are used to blend two compositing nodes according to a given `Equation` and
  /// two blending `Factor`s for source and destination, respectively.
  Composite(Box<Node<'a>>, Box<Node<'a>>, Equation, Factor, Factor)
}

impl<'a> Node<'a> {
  /// Compose this node with another one.
  pub fn compose_with(self, other: Self, eq: Equation, src_fct: Factor, dst_fct: Factor) -> Self {
    Node::Composite(Box::new(self), Box::new(other), eq, src_fct, dst_fct)
  }
}

impl<'a> From<LayerRender<'a>> for Node<'a> {
  fn from(layer: LayerRender<'a>) -> Self {
    Node::Render(layer)
  }
}

impl<'a> From<LayerTexture<'a>> for Node<'a> {
  fn from(texture: LayerTexture<'a>) -> Self {
    Node::Texture(texture)
  }
}

impl<'a> Add for Node<'a> {
  type Output = Self;

  fn add(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::One, Factor::One)
  }
}

impl<'a> Sub for Node<'a> {
  type Output = Self;

  fn sub(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Subtract, Factor::One, Factor::One)
  }
}

impl<'a> Mul for Node<'a> {
  type Output = Self;

  fn mul(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::One, Factor::SrcColor)
  }
}

/// Compositor object; used to consume `Node`s and output to screen.
pub struct Compositor {
}
<commit_msg>Fixed impl<'a> Mul for Node<'a>.<commit_after>use luminance::{Depth32F, Dim2, Flat, Texture, RGBA32F};
use std::ops::{Add, Sub, Mul};

pub use luminance::{Equation, Factor};

/// Layer render that can be embedded into a compositing graph.
pub type LayerRender<'a> = (ColorMap<'a>, DepthMap<'a>);
/// Simple texture that can be embedded into a compositing graph.
pub type LayerTexture<'a> = ColorMap<'a>;

pub type ColorMap<'a> = &'a Texture<Flat, Dim2, RGBA32F>;
pub type DepthMap<'a> = &'a Texture<Flat, Dim2, Depth32F>;

/// Compositing node.
pub enum Node<'a> {
  /// A render node.
  ///
  /// Contains a color map and a depth map.
  Render(LayerRender<'a>),
  /// A texture node.
  ///
  /// Contains a single texture.
  Texture(LayerTexture<'a>),
  /// Composite node.
  ///
  /// Composite nodes are used to blend two compositing nodes according to a given `Equation` and
  /// two blending `Factor`s for source and destination, respectively.
  Composite(Box<Node<'a>>, Box<Node<'a>>, Equation, Factor, Factor)
}

impl<'a> Node<'a> {
  /// Compose this node with another one.
  pub fn compose_with(self, other: Self, eq: Equation, src_fct: Factor, dst_fct: Factor) -> Self {
    Node::Composite(Box::new(self), Box::new(other), eq, src_fct, dst_fct)
  }
}

impl<'a> From<LayerRender<'a>> for Node<'a> {
  fn from(layer: LayerRender<'a>) -> Self {
    Node::Render(layer)
  }
}

impl<'a> From<LayerTexture<'a>> for Node<'a> {
  fn from(texture: LayerTexture<'a>) -> Self {
    Node::Texture(texture)
  }
}

impl<'a> Add for Node<'a> {
  type Output = Self;

  fn add(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::One, Factor::One)
  }
}

impl<'a> Sub for Node<'a> {
  type Output = Self;

  fn sub(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Subtract, Factor::One, Factor::One)
  }
}

impl<'a> Mul for Node<'a> {
  type Output = Self;

  fn mul(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::Zero, Factor::SrcColor)
  }
}

/// Compositor object; used to consume `Node`s and output to screen.
pub struct Compositor {
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate dft;
extern crate test;

use std::mem;
use dft::{Operation, Plan, c64};
use test::{Bencher, black_box};

#[bench] fn complex_0004(bencher: &mut Bencher) { complex(   4, bencher); }
#[bench] fn complex_0008(bencher: &mut Bencher) { complex(   8, bencher); }
#[bench] fn complex_0016(bencher: &mut Bencher) { complex(  16, bencher); }
#[bench] fn complex_0032(bencher: &mut Bencher) { complex(  32, bencher); }
#[bench] fn complex_0064(bencher: &mut Bencher) { complex(  64, bencher); }
#[bench] fn complex_0128(bencher: &mut Bencher) { complex( 128, bencher); }
#[bench] fn complex_0256(bencher: &mut Bencher) { complex( 256, bencher); }
#[bench] fn complex_0512(bencher: &mut Bencher) { complex( 512, bencher); }
#[bench] fn complex_1024(bencher: &mut Bencher) { complex(1024, bencher); }
#[bench] fn complex_2048(bencher: &mut Bencher) { complex(2048, bencher); }
#[bench] fn complex_4096(bencher: &mut Bencher) { complex(4096, bencher); }
#[bench] fn complex_8192(bencher: &mut Bencher) { complex(8192, bencher); }

#[bench] fn real_0004(bencher: &mut Bencher) { real(   4, bencher); }
#[bench] fn real_0008(bencher: &mut Bencher) { real(   8, bencher); }
#[bench] fn real_0016(bencher: &mut Bencher) { real(  16, bencher); }
#[bench] fn real_0032(bencher: &mut Bencher) { real(  32, bencher); }
#[bench] fn real_0064(bencher: &mut Bencher) { real(  64, bencher); }
#[bench] fn real_0128(bencher: &mut Bencher) { real( 128, bencher); }
#[bench] fn real_0256(bencher: &mut Bencher) { real( 256, bencher); }
#[bench] fn real_0512(bencher: &mut Bencher) { real( 512, bencher); }
#[bench] fn real_1024(bencher: &mut Bencher) { real(1024, bencher); }
#[bench] fn real_2048(bencher: &mut Bencher) { real(2048, bencher); }
#[bench] fn real_4096(bencher: &mut Bencher) { real(4096, bencher); }
#[bench] fn real_8192(bencher: &mut Bencher) { real(8192, bencher); }

fn complex(size: usize, bencher: &mut Bencher) {
    let mut data = vec![c64::new(42.0, 69.0); size];
    let plan = Plan::new(Operation::Forward, size);
    bencher.bytes = (data.len() * mem::size_of_val(&data[0])) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}

fn real(size: usize, bencher: &mut Bencher) {
    let mut data = vec![42.0; 2 * size];
    let plan = Plan::new(Operation::Forward, 2 * size);
    bencher.bytes = (data.len() * mem::size_of_val(&data[0])) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}
<commit_msg>Use size_of instead of size_of_val in the benchmarks<commit_after>#![feature(test)]

extern crate dft;
extern crate test;

use std::mem;

use dft::{Operation, Plan, c64};
use test::{Bencher, black_box};

#[bench] fn complex_0004(bencher: &mut Bencher) { complex(   4, bencher); }
#[bench] fn complex_0008(bencher: &mut Bencher) { complex(   8, bencher); }
#[bench] fn complex_0016(bencher: &mut Bencher) { complex(  16, bencher); }
#[bench] fn complex_0032(bencher: &mut Bencher) { complex(  32, bencher); }
#[bench] fn complex_0064(bencher: &mut Bencher) { complex(  64, bencher); }
#[bench] fn complex_0128(bencher: &mut Bencher) { complex( 128, bencher); }
#[bench] fn complex_0256(bencher: &mut Bencher) { complex( 256, bencher); }
#[bench] fn complex_0512(bencher: &mut Bencher) { complex( 512, bencher); }
#[bench] fn complex_1024(bencher: &mut Bencher) { complex(1024, bencher); }
#[bench] fn complex_2048(bencher: &mut Bencher) { complex(2048, bencher); }
#[bench] fn complex_4096(bencher: &mut Bencher) { complex(4096, bencher); }
#[bench] fn complex_8192(bencher: &mut Bencher) { complex(8192, bencher); }

#[bench] fn real_0004(bencher: &mut Bencher) { real(   4, bencher); }
#[bench] fn real_0008(bencher: &mut Bencher) { real(   8, bencher); }
#[bench] fn real_0016(bencher: &mut Bencher) { real(  16, bencher); }
#[bench] fn real_0032(bencher: &mut Bencher) { real(  32, bencher); }
#[bench] fn real_0064(bencher: &mut Bencher) { real(  64, bencher); }
#[bench] fn real_0128(bencher: &mut Bencher) { real( 128, bencher); }
#[bench] fn real_0256(bencher: &mut Bencher) { real( 256, bencher); }
#[bench] fn real_0512(bencher: &mut Bencher) { real( 512, bencher); }
#[bench] fn real_1024(bencher: &mut Bencher) { real(1024, bencher); }
#[bench] fn real_2048(bencher: &mut Bencher) { real(2048, bencher); }
#[bench] fn real_4096(bencher: &mut Bencher) { real(4096, bencher); }
#[bench] fn real_8192(bencher: &mut Bencher) { real(8192, bencher); }

fn complex(size: usize, bencher: &mut Bencher) {
    let mut data = vec![c64::new(42.0, 69.0); size];
    let plan = Plan::new(Operation::Forward, size);
    bencher.bytes = (data.len() * mem::size_of::<c64>()) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}

fn real(size: usize, bencher: &mut Bencher) {
    let mut data = vec![42.0; 2 * size];
    let plan = Plan::new(Operation::Forward, 2 * size);
    bencher.bytes = (data.len() * mem::size_of::<f64>()) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}
<|endoftext|>


<commit_before>use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
use std::fmt;

/// Uniquely identifies a node in the HIR of the current crate. It is
/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
/// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
/// and the `local_id` which is unique within the given owner.
///
/// This two-level structure makes for more stable values: One can move an item
/// around within the source code, or add or remove stuff before it, without
/// the `local_id` part of the `HirId` changing, which is a very useful property in
/// incremental compilation where we have to persist things through changes to
/// the code base.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
#[derive(Encodable, Decodable)]
pub struct HirId {
    pub owner: LocalDefId,
    pub local_id: ItemLocalId,
}

impl HirId {
    pub fn expect_owner(self) -> LocalDefId {
        assert_eq!(self.local_id.index(), 0);
        self.owner
    }

    pub fn as_owner(self) -> Option<LocalDefId> {
        if self.local_id.index() == 0 { Some(self.owner) } else { None }
    }

    #[inline]
    pub fn make_owner(owner: LocalDefId) -> Self {
        Self { owner, local_id: ItemLocalId::from_u32(0) }
    }
}

impl fmt::Display for HirId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

rustc_data_structures::define_id_collections!(HirIdMap, HirIdSet, HirId);
rustc_data_structures::define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId);

rustc_index::newtype_index! {
    /// An `ItemLocalId` uniquely identifies something within a given "item-like";
    /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no
    /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
    /// the node's position within the owning item in any way, but there is a
    /// guarantee that the `LocalItemId`s within an owner occupy a dense range of
    /// integers starting at zero, so a mapping that maps all or most nodes within
    /// an "item-like" to something else can be implemented by a `Vec` instead of a
    /// tree or hash map.
    pub struct ItemLocalId { .. }
}
rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId);

/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`.
pub const CRATE_HIR_ID: HirId = HirId {
    owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
    local_id: ItemLocalId::from_u32(0),
};
<commit_msg>Introduce HirIdVec.<commit_after>use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
use rustc_index::vec::IndexVec;
use std::fmt;

/// Uniquely identifies a node in the HIR of the current crate. It is
/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
/// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
/// and the `local_id` which is unique within the given owner.
///
/// This two-level structure makes for more stable values: One can move an item
/// around within the source code, or add or remove stuff before it, without
/// the `local_id` part of the `HirId` changing, which is a very useful property in
/// incremental compilation where we have to persist things through changes to
/// the code base.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
#[derive(Encodable, Decodable)]
pub struct HirId {
    pub owner: LocalDefId,
    pub local_id: ItemLocalId,
}

impl HirId {
    pub fn expect_owner(self) -> LocalDefId {
        assert_eq!(self.local_id.index(), 0);
        self.owner
    }

    pub fn as_owner(self) -> Option<LocalDefId> {
        if self.local_id.index() == 0 { Some(self.owner) } else { None }
    }

    #[inline]
    pub fn make_owner(owner: LocalDefId) -> Self {
        Self { owner, local_id: ItemLocalId::from_u32(0) }
    }
}

impl fmt::Display for HirId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

rustc_data_structures::define_id_collections!(HirIdMap, HirIdSet, HirId);
rustc_data_structures::define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId);

rustc_index::newtype_index! {
    /// An `ItemLocalId` uniquely identifies something within a given "item-like";
    /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no
    /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
    /// the node's position within the owning item in any way, but there is a
    /// guarantee that the `LocalItemId`s within an owner occupy a dense range of
    /// integers starting at zero, so a mapping that maps all or most nodes within
    /// an "item-like" to something else can be implemented by a `Vec` instead of a
    /// tree or hash map.
    pub struct ItemLocalId { .. }
}
rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId);

/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`.
pub const CRATE_HIR_ID: HirId = HirId {
    owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
    local_id: ItemLocalId::from_u32(0),
};

#[derive(Clone, Default, Debug, Encodable, Decodable)]
pub struct HirIdVec<T> {
    map: IndexVec<LocalDefId, IndexVec<ItemLocalId, T>>,
}

impl<T> HirIdVec<T> {
    pub fn push_owner(&mut self, id: LocalDefId) {
        self.map.ensure_contains_elem(id, IndexVec::new);
    }

    pub fn push(&mut self, id: HirId, value: T) {
        if id.local_id == ItemLocalId::from_u32(0) {
            self.push_owner(id.owner);
        }
        let submap = &mut self.map[id.owner];
        let _ret_id = submap.push(value);
        debug_assert_eq!(_ret_id, id.local_id);
    }

    pub fn get(&self, id: HirId) -> Option<&T> {
        self.map.get(id.owner)?.get(id.local_id)
    }

    pub fn get_owner(&self, id: LocalDefId) -> &IndexVec<ItemLocalId, T> {
        &self.map[id]
    }

    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.map.iter().flat_map(|la| la.iter())
    }

    pub fn iter_enumerated(&self) -> impl Iterator<Item = (HirId, &T)> {
        self.map.iter_enumerated().flat_map(|(owner, la)| {
            la.iter_enumerated().map(move |(local_id, attr)| (HirId { owner, local_id }, attr))
        })
    }
}

impl<T> std::ops::Index<HirId> for HirIdVec<T> {
    type Output = T;

    fn index(&self, id: HirId) -> &T {
        &self.map[id.owner][id.local_id]
    }
}

impl<T> std::ops::IndexMut<HirId> for HirIdVec<T> {
    fn index_mut(&mut self, id: HirId) -> &mut T {
        &mut self.map[id.owner][id.local_id]
    }
}
<|endoftext|>


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

use dom::bindings::codegen::Bindings::StorageBinding;
use dom::bindings::codegen::Bindings::StorageBinding::StorageMethods;
use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root, RootedReference};
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::storageevent::StorageEvent;
use dom::urlhelper::UrlHelper;
use ipc_channel::ipc;
use net_traits::storage_thread::{StorageThread, StorageThreadMsg, StorageType};
use page::IterablePage;
use script_runtime::ScriptChan;
use script_thread::{MainThreadRunnable, MainThreadScriptChan, ScriptThread};
use task_source::dom_manipulation::DOMManipulationTask;
use url::Url;
use util::str::DOMString;

#[dom_struct]
pub struct Storage {
    reflector_: Reflector,
    storage_type: StorageType
}

impl Storage {
    fn new_inherited(storage_type: StorageType) -> Storage {
        Storage {
            reflector_: Reflector::new(),
            storage_type: storage_type
        }
    }

    pub fn new(global: &GlobalRef, storage_type: StorageType) -> Root<Storage> {
        reflect_dom_object(box Storage::new_inherited(storage_type), *global, StorageBinding::Wrap)
    }

    fn get_url(&self) -> Url {
        let global_root = self.global();
        let global_ref = global_root.r();
        global_ref.get_url()
    }

    fn get_storage_thread(&self) -> StorageThread {
        let global_root = self.global();
        let global_ref = global_root.r();
        global_ref.as_window().storage_thread()
    }

}

impl StorageMethods for Storage {
    // https://html.spec.whatwg.org/multipage/#dom-storage-length
    fn Length(&self) -> u32 {
        let (sender, receiver) = ipc::channel().unwrap();

        self.get_storage_thread().send(StorageThreadMsg::Length(sender, self.get_url(), self.storage_type)).unwrap();
        receiver.recv().unwrap() as u32
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-key
    fn Key(&self, index: u32) -> Option<DOMString> {
        let (sender, receiver) = ipc::channel().unwrap();

        self.get_storage_thread()
            .send(StorageThreadMsg::Key(sender, self.get_url(), self.storage_type, index))
            .unwrap();
        receiver.recv().unwrap().map(DOMString::from)
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-getitem
    fn GetItem(&self, name: DOMString) -> Option<DOMString> {
        let (sender, receiver) = ipc::channel().unwrap();
        let name = String::from(name);

        let msg = StorageThreadMsg::GetItem(sender, self.get_url(), self.storage_type, name);
        self.get_storage_thread().send(msg).unwrap();
        receiver.recv().unwrap().map(DOMString::from)
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-setitem
    fn SetItem(&self, name: DOMString, value: DOMString) -> ErrorResult {
        let (sender, receiver) = ipc::channel().unwrap();
        let name = String::from(name);
        let value = String::from(value);

        let msg = StorageThreadMsg::SetItem(sender, self.get_url(), self.storage_type, name.clone(), value.clone());
        self.get_storage_thread().send(msg).unwrap();
        match receiver.recv().unwrap() {
            Err(_) => Err(Error::QuotaExceeded),
            Ok((changed, old_value)) => {
              if changed {
                  self.broadcast_change_notification(Some(name), old_value, Some(value));
              }
              Ok(())
            }
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-removeitem
    fn RemoveItem(&self, name: DOMString) {
        let (sender, receiver) = ipc::channel().unwrap();
        let name = String::from(name);

        let msg = StorageThreadMsg::RemoveItem(sender, self.get_url(), self.storage_type, name.clone());
        self.get_storage_thread().send(msg).unwrap();
        if let Some(old_value) = receiver.recv().unwrap() {
            self.broadcast_change_notification(Some(name), Some(old_value), None);
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-clear
    fn Clear(&self) {
        let (sender, receiver) = ipc::channel().unwrap();

        self.get_storage_thread().send(StorageThreadMsg::Clear(sender, self.get_url(), self.storage_type)).unwrap();
        if receiver.recv().unwrap() {
            self.broadcast_change_notification(None, None, None);
        }
    }

    // https://html.spec.whatwg.org/multipage/#the-storage-interface:supported-property-names
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        let (sender, receiver) = ipc::channel().unwrap();

        self.get_storage_thread().send(StorageThreadMsg::Keys(sender, self.get_url(), self.storage_type)).unwrap();
        receiver.recv().unwrap().iter().cloned().map(DOMString::from).collect() // FIXME: inefficient?
    }

    // check-tidy: no specs after this line
    fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<DOMString> {
        let item = self.GetItem(name);
        *found = item.is_some();
        item
    }

    fn NamedSetter(&self, name: DOMString, value: DOMString) -> ErrorResult {
        self.SetItem(name, value)
    }

    fn NamedDeleter(&self, name: DOMString) {
        self.RemoveItem(name);
    }
}

impl Storage {
    /// https://html.spec.whatwg.org/multipage/#send-a-storage-notification
    fn broadcast_change_notification(&self, key: Option<String>, old_value: Option<String>,
                                     new_value: Option<String>) {
        let global_root = self.global();
        let global_ref = global_root.r();
        let task_source = global_ref.as_window().dom_manipulation_task_source();
        let chan = MainThreadScriptChan(global_ref.as_window().main_thread_script_chan().clone()).clone();
        let trusted_storage = Trusted::new(self, chan);
        task_source.queue(DOMManipulationTask::SendStorageNotification(
            box StorageEventRunnable::new(trusted_storage, key, old_value, new_value))).unwrap();
    }
}

pub struct StorageEventRunnable {
    element: Trusted<Storage>,
    key: Option<String>,
    old_value: Option<String>,
    new_value: Option<String>
}

impl StorageEventRunnable {
    fn new(storage: Trusted<Storage>, key: Option<String>, old_value: Option<String>,
           new_value: Option<String>) -> StorageEventRunnable {
        StorageEventRunnable { element: storage, key: key, old_value: old_value, new_value: new_value }
    }
}

impl MainThreadRunnable for StorageEventRunnable {
    fn handler(self: Box<StorageEventRunnable>, script_thread: &ScriptThread) {
        let this = *self;
        let storage_root = this.element.root();
        let storage = storage_root.r();
        let global_root = storage.global();
        let global_ref = global_root.r();
        let ev_window = global_ref.as_window();
        let ev_url = storage.get_url();

        let storage_event = StorageEvent::new(
            global_ref,
            atom!("storage"),
            EventBubbles::DoesNotBubble, EventCancelable::NotCancelable,
            this.key.map(DOMString::from), this.old_value.map(DOMString::from), this.new_value.map(DOMString::from),
            DOMString::from(ev_url.to_string()),
            Some(storage)
        );

        let root_page = script_thread.root_page();
        for it_page in root_page.iter() {
            let it_window_root = it_page.window();
            let it_window = it_window_root.r();
            assert!(UrlHelper::SameOrigin(&ev_url, &it_window.get_url()));
            // TODO: Such a Document object is not necessarily fully active, but events fired on such
            // objects are ignored by the event loop until the Document becomes fully active again.
            if ev_window.pipeline() != it_window.pipeline() {
                storage_event.upcast::<Event>().fire(it_window.upcast());
            }
        }
    }
}
<commit_msg>Complete 'inefficient' FIXME by remove unnecessary clone.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::StorageBinding;
use dom::bindings::codegen::Bindings::StorageBinding::StorageMethods;
use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root, RootedReference};
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::storageevent::StorageEvent;
use dom::urlhelper::UrlHelper;
use ipc_channel::ipc;
use net_traits::storage_thread::{StorageThread, StorageThreadMsg, StorageType};
use page::IterablePage;
use script_runtime::ScriptChan;
use script_thread::{MainThreadRunnable, MainThreadScriptChan, ScriptThread};
use task_source::dom_manipulation::DOMManipulationTask;
use url::Url;
use util::str::DOMString;

#[dom_struct]
pub struct Storage {
    reflector_: Reflector,
    storage_type: StorageType
}

impl Storage {
    fn new_inherited(storage_type: StorageType) -> Storage {
        Storage {
            reflector_: Reflector::new(),
            storage_type: storage_type
        }
    }

    pub fn new(global: &GlobalRef, storage_type: StorageType) -> Root<Storage> {
        reflect_dom_object(box Storage::new_inherited(storage_type), *global, StorageBinding::Wrap)
    }

    fn get_url(&self) -> Url {
        let global_root = self.global();
        let global_ref = global_root.r();
        global_ref.get_url()
    }

    fn get_storage_thread(&self) -> StorageThread {
        let global_root = self.global();
        let global_ref = global_root.r();
        global_ref.as_window().storage_thread()
    }

}

impl StorageMethods for Storage {
    // https://html.spec.whatwg.org/multipage/#dom-storage-length
    fn Length(&self) -> u32 {
        let (sender, receiver) = ipc::channel().unwrap();

        self.get_storage_thread().send(StorageThreadMsg::Length(sender, self.get_url(), self.storage_type)).unwrap();
        receiver.recv().unwrap() as u32
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-key
    fn Key(&self, index: u32) -> Option<DOMString> {
        let (sender, receiver) = ipc::channel().unwrap();

        self.get_storage_thread()
            .send(StorageThreadMsg::Key(sender, self.get_url(), self.storage_type, index))
            .unwrap();
        receiver.recv().unwrap().map(DOMString::from)
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-getitem
    fn GetItem(&self, name: DOMString) -> Option<DOMString> {
        let (sender, receiver) = ipc::channel().unwrap();
        let name = String::from(name);

        let msg = StorageThreadMsg::GetItem(sender, self.get_url(), self.storage_type, name);
        self.get_storage_thread().send(msg).unwrap();
        receiver.recv().unwrap().map(DOMString::from)
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-setitem
    fn SetItem(&self, name: DOMString, value: DOMString) -> ErrorResult {
        let (sender, receiver) = ipc::channel().unwrap();
        let name = String::from(name);
        let value = String::from(value);

        let msg = StorageThreadMsg::SetItem(sender, self.get_url(), self.storage_type, name.clone(), value.clone());
        self.get_storage_thread().send(msg).unwrap();
        match receiver.recv().unwrap() {
            Err(_) => Err(Error::QuotaExceeded),
            Ok((changed, old_value)) => {
              if changed {
                  self.broadcast_change_notification(Some(name), old_value, Some(value));
              }
              Ok(())
            }
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-removeitem
    fn RemoveItem(&self, name: DOMString) {
        let (sender, receiver) = ipc::channel().unwrap();
        let name = String::from(name);

        let msg = StorageThreadMsg::RemoveItem(sender, self.get_url(), self.storage_type, name.clone());
        self.get_storage_thread().send(msg).unwrap();
        if let Some(old_value) = receiver.recv().unwrap() {
            self.broadcast_change_notification(Some(name), Some(old_value), None);
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-storage-clear
    fn Clear(&self) {
        let (sender, receiver) = ipc::channel().unwrap();

        self.get_storage_thread().send(StorageThreadMsg::Clear(sender, self.get_url(), self.storage_type)).unwrap();
        if receiver.recv().unwrap() {
            self.broadcast_change_notification(None, None, None);
        }
    }

    // https://html.spec.whatwg.org/multipage/#the-storage-interface:supported-property-names
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        let (sender, receiver) = ipc::channel().unwrap();

        self.get_storage_thread().send(StorageThreadMsg::Keys(sender, self.get_url(), self.storage_type)).unwrap();
        receiver.recv()
                .unwrap()
                .into_iter()
                .map(DOMString::from)
                .collect()
    }

    // check-tidy: no specs after this line
    fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<DOMString> {
        let item = self.GetItem(name);
        *found = item.is_some();
        item
    }

    fn NamedSetter(&self, name: DOMString, value: DOMString) -> ErrorResult {
        self.SetItem(name, value)
    }

    fn NamedDeleter(&self, name: DOMString) {
        self.RemoveItem(name);
    }
}

impl Storage {
    /// https://html.spec.whatwg.org/multipage/#send-a-storage-notification
    fn broadcast_change_notification(&self, key: Option<String>, old_value: Option<String>,
                                     new_value: Option<String>) {
        let global_root = self.global();
        let global_ref = global_root.r();
        let task_source = global_ref.as_window().dom_manipulation_task_source();
        let chan = MainThreadScriptChan(global_ref.as_window().main_thread_script_chan().clone()).clone();
        let trusted_storage = Trusted::new(self, chan);
        task_source.queue(DOMManipulationTask::SendStorageNotification(
            box StorageEventRunnable::new(trusted_storage, key, old_value, new_value))).unwrap();
    }
}

pub struct StorageEventRunnable {
    element: Trusted<Storage>,
    key: Option<String>,
    old_value: Option<String>,
    new_value: Option<String>
}

impl StorageEventRunnable {
    fn new(storage: Trusted<Storage>, key: Option<String>, old_value: Option<String>,
           new_value: Option<String>) -> StorageEventRunnable {
        StorageEventRunnable { element: storage, key: key, old_value: old_value, new_value: new_value }
    }
}

impl MainThreadRunnable for StorageEventRunnable {
    fn handler(self: Box<StorageEventRunnable>, script_thread: &ScriptThread) {
        let this = *self;
        let storage_root = this.element.root();
        let storage = storage_root.r();
        let global_root = storage.global();
        let global_ref = global_root.r();
        let ev_window = global_ref.as_window();
        let ev_url = storage.get_url();

        let storage_event = StorageEvent::new(
            global_ref,
            atom!("storage"),
            EventBubbles::DoesNotBubble, EventCancelable::NotCancelable,
            this.key.map(DOMString::from), this.old_value.map(DOMString::from), this.new_value.map(DOMString::from),
            DOMString::from(ev_url.to_string()),
            Some(storage)
        );

        let root_page = script_thread.root_page();
        for it_page in root_page.iter() {
            let it_window_root = it_page.window();
            let it_window = it_window_root.r();
            assert!(UrlHelper::SameOrigin(&ev_url, &it_window.get_url()));
            // TODO: Such a Document object is not necessarily fully active, but events fired on such
            // objects are ignored by the event loop until the Document becomes fully active again.
            if ev_window.pipeline() != it_window.pipeline() {
                storage_event.upcast::<Event>().fire(it_window.upcast());
            }
        }
    }
}
<|endoftext|>


<commit_before>use crypt32;
use std::io;
use std::mem;
use std::ptr;
use winapi;

use cert_context::CertContext;
use Inner;

pub struct CtlContext(winapi::PCCTL_CONTEXT);

unsafe impl Send for CtlContext {}
unsafe impl Sync for CtlContext {}

impl Drop for CtlContext {
	fn drop(&mut self) {
		unsafe {
			crypt32::CertFreeCTLContext(self.0);
		}
	}
}

impl Inner<winapi::PCCTL_CONTEXT> for CtlContext {
	unsafe fn from_inner(t: winapi::PCCTL_CONTEXT) -> CtlContext {
		CtlContext(t)
	}

	fn as_inner(&self) -> winapi::PCCTL_CONTEXT {
		self.0
	}

	fn get_mut(&mut self) -> &mut winapi::PCCTL_CONTEXT {
		&mut self.0
	}
}

impl CtlContext {
	pub fn builder() -> Builder {
		Builder {
			certificates: vec![],
			usages: vec![],
		}
	}
}

pub struct Builder {
	certificates: Vec<CertContext>,
	usages: Vec<Vec<u8>>,
}

impl Builder {
	pub fn certificate(&mut self, cert: CertContext) -> &mut Builder {
		self.certificates.push(cert);
		self
	}

	pub fn usage(&mut self, usage: &str) -> &mut Builder {
		let mut usage = usage.as_bytes().to_owned();
		usage.push(0);
		self.usages.push(usage);
		self
	}

	pub fn encode_and_sign(&self) -> io::Result<Vec<u8>> {
		unsafe {
			let encoding = winapi::X509_ASN_ENCODING | winapi::PKCS_7_ASN_ENCODING;

			let mut usages = self.usages.iter().map(|u| u.as_ptr()).collect::<Vec<_>>();
			let mut entry_data = vec![];
			let mut entries = vec![];
			for certificate in &self.certificates {
				let data = try!(cert_entry(certificate));
				entries.push(*(data.as_ptr() as *const winapi::CTL_ENTRY));
				entry_data.push(data);
			}

			let mut ctl_info: winapi::CTL_INFO = mem::zeroed();
			ctl_info.dwVersion = winapi::CTL_V1;
			ctl_info.SubjectUsage.cUsageIdentifier = usages.len() as winapi::DWORD;
			ctl_info.SubjectUsage.rgpszUsageIdentifier = usages.as_mut_ptr() as *mut winapi::LPSTR;
			let mut algorithm = winapi::szOID_OIWSEC_sha1.as_bytes().to_owned();
			algorithm.push(0);
			ctl_info.SubjectAlgorithm.pszObjId = algorithm.as_ptr() as winapi::LPSTR;
			ctl_info.cCTLEntry = entries.len() as winapi::DWORD;
			ctl_info.rgCTLEntry = entries.as_mut_ptr();

			let mut sign_info: winapi::CMSG_SIGNED_ENCODE_INFO = mem::zeroed();
			sign_info.cbSize = mem::size_of_val(&sign_info) as winapi::DWORD;
			let mut encoded_certs = self.certificates
										.iter()
										.map(|c| {
											winapi::CERT_BLOB {
												cbData: (*c.as_inner()).cbCertEncoded,
												pbData: (*c.as_inner()).pbCertEncoded,
											}
										})
										.collect::<Vec<_>>();
			sign_info.rgCertEncoded = encoded_certs.as_mut_ptr();
			sign_info.cCertEncoded = encoded_certs.len() as winapi::DWORD;

			let flags = winapi::CMSG_ENCODE_SORTED_CTL_FLAG |
				winapi::CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG;

			let mut size = 0;

			let res = crypt32::CryptMsgEncodeAndSignCTL(
				encoding,
				&mut ctl_info,
				&mut sign_info,
				flags,
				ptr::null_mut(),
				&mut size);
			if res == winapi::FALSE {
				return Err(io::Error::last_os_error());
			}

			let mut encoded = vec![0; size as usize];

			let res = crypt32::CryptMsgEncodeAndSignCTL(
				encoding,
				&mut ctl_info,
				&mut sign_info,
				flags,
				encoded.as_mut_ptr() as *mut winapi::BYTE,
				&mut size);
			if res == winapi::FALSE {
				return Err(io::Error::last_os_error());
			}

			Ok(encoded)
		}
	}
}

fn cert_entry(cert: &CertContext) -> io::Result<Vec<u8>> {
	unsafe {
		let mut size = 0;

		let res = crypt32::CertCreateCTLEntryFromCertificateContextProperties(
			cert.as_inner(),
			0,
			ptr::null_mut(),
			winapi::CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
			ptr::null_mut(),
			ptr::null_mut(),
			&mut size);
		if res == winapi::FALSE {
			return Err(io::Error::last_os_error());
		}

		let mut entry = vec![0; size as usize];
		let res = crypt32::CertCreateCTLEntryFromCertificateContextProperties(
			cert.as_inner(),
			0,
			ptr::null_mut(),
			winapi::CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
			ptr::null_mut(),
			entry.as_mut_ptr() as winapi::PCTL_ENTRY,
			&mut size);
		if res == winapi::FALSE {
			Err(io::Error::last_os_error())
		} else {
			Ok(entry)
		}
	}
}

#[cfg(test)]
mod test {
	use std::io::Read;
	use std::fs::File;
	use cert_store::CertStore;
	use ctl_context::CtlContext;

	#[test]
	fn create_ctl() {
        let mut file = File::open(concat!(env!("CARGO_MANIFEST_DIR"),
                                          "/test/self-signed.badssl.com.cer"))
                           .unwrap();
        let mut cert = vec![];
        file.read_to_end(&mut cert).unwrap();

        let mut store = CertStore::memory().unwrap();
        let cert = store.add_encoded_certificate(&cert).unwrap();

        CtlContext::builder()
        	.certificate(cert)
            .usage("1.3.6.1.4.1.311.2.2.2")
            .encode_and_sign()
            .unwrap();
	}
}<commit_msg>Add a lazy static for ctl signature algorithm<commit_after>use crypt32;
use std::io;
use std::mem;
use std::ptr;
use winapi;

use cert_context::CertContext;
use Inner;

lazy_static! {
	static ref szOID_OIWSEC_sha1: Vec<u8> =
		winapi::szOID_OIWSEC_sha1.bytes().chain(Some(0)).collect();
}

pub struct CtlContext(winapi::PCCTL_CONTEXT);

unsafe impl Send for CtlContext {}
unsafe impl Sync for CtlContext {}

impl Drop for CtlContext {
	fn drop(&mut self) {
		unsafe {
			crypt32::CertFreeCTLContext(self.0);
		}
	}
}

impl Inner<winapi::PCCTL_CONTEXT> for CtlContext {
	unsafe fn from_inner(t: winapi::PCCTL_CONTEXT) -> CtlContext {
		CtlContext(t)
	}

	fn as_inner(&self) -> winapi::PCCTL_CONTEXT {
		self.0
	}

	fn get_mut(&mut self) -> &mut winapi::PCCTL_CONTEXT {
		&mut self.0
	}
}

impl CtlContext {
	pub fn builder() -> Builder {
		Builder {
			certificates: vec![],
			usages: vec![],
		}
	}
}

pub struct Builder {
	certificates: Vec<CertContext>,
	usages: Vec<Vec<u8>>,
}

impl Builder {
	pub fn certificate(&mut self, cert: CertContext) -> &mut Builder {
		self.certificates.push(cert);
		self
	}

	pub fn usage(&mut self, usage: &str) -> &mut Builder {
		let mut usage = usage.as_bytes().to_owned();
		usage.push(0);
		self.usages.push(usage);
		self
	}

	pub fn encode_and_sign(&self) -> io::Result<Vec<u8>> {
		unsafe {
			let encoding = winapi::X509_ASN_ENCODING | winapi::PKCS_7_ASN_ENCODING;

			let mut usages = self.usages.iter().map(|u| u.as_ptr()).collect::<Vec<_>>();
			let mut entry_data = vec![];
			let mut entries = vec![];
			for certificate in &self.certificates {
				let data = try!(cert_entry(certificate));
				entries.push(*(data.as_ptr() as *const winapi::CTL_ENTRY));
				entry_data.push(data);
			}

			let mut ctl_info: winapi::CTL_INFO = mem::zeroed();
			ctl_info.dwVersion = winapi::CTL_V1;
			ctl_info.SubjectUsage.cUsageIdentifier = usages.len() as winapi::DWORD;
			ctl_info.SubjectUsage.rgpszUsageIdentifier = usages.as_mut_ptr() as *mut winapi::LPSTR;
			ctl_info.SubjectAlgorithm.pszObjId = szOID_OIWSEC_sha1.as_ptr() as winapi::LPSTR;
			ctl_info.cCTLEntry = entries.len() as winapi::DWORD;
			ctl_info.rgCTLEntry = entries.as_mut_ptr();

			let mut sign_info: winapi::CMSG_SIGNED_ENCODE_INFO = mem::zeroed();
			sign_info.cbSize = mem::size_of_val(&sign_info) as winapi::DWORD;
			let mut encoded_certs = self.certificates
										.iter()
										.map(|c| {
											winapi::CERT_BLOB {
												cbData: (*c.as_inner()).cbCertEncoded,
												pbData: (*c.as_inner()).pbCertEncoded,
											}
										})
										.collect::<Vec<_>>();
			sign_info.rgCertEncoded = encoded_certs.as_mut_ptr();
			sign_info.cCertEncoded = encoded_certs.len() as winapi::DWORD;

			let flags = winapi::CMSG_ENCODE_SORTED_CTL_FLAG |
				winapi::CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG;

			let mut size = 0;

			let res = crypt32::CryptMsgEncodeAndSignCTL(
				encoding,
				&mut ctl_info,
				&mut sign_info,
				flags,
				ptr::null_mut(),
				&mut size);
			if res == winapi::FALSE {
				return Err(io::Error::last_os_error());
			}

			let mut encoded = vec![0; size as usize];

			let res = crypt32::CryptMsgEncodeAndSignCTL(
				encoding,
				&mut ctl_info,
				&mut sign_info,
				flags,
				encoded.as_mut_ptr() as *mut winapi::BYTE,
				&mut size);
			if res == winapi::FALSE {
				return Err(io::Error::last_os_error());
			}

			Ok(encoded)
		}
	}
}

fn cert_entry(cert: &CertContext) -> io::Result<Vec<u8>> {
	unsafe {
		let mut size = 0;

		let res = crypt32::CertCreateCTLEntryFromCertificateContextProperties(
			cert.as_inner(),
			0,
			ptr::null_mut(),
			winapi::CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
			ptr::null_mut(),
			ptr::null_mut(),
			&mut size);
		if res == winapi::FALSE {
			return Err(io::Error::last_os_error());
		}

		let mut entry = vec![0; size as usize];
		let res = crypt32::CertCreateCTLEntryFromCertificateContextProperties(
			cert.as_inner(),
			0,
			ptr::null_mut(),
			winapi::CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
			ptr::null_mut(),
			entry.as_mut_ptr() as winapi::PCTL_ENTRY,
			&mut size);
		if res == winapi::FALSE {
			Err(io::Error::last_os_error())
		} else {
			Ok(entry)
		}
	}
}

#[cfg(test)]
mod test {
	use std::io::Read;
	use std::fs::File;
	use cert_store::CertStore;
	use ctl_context::CtlContext;

	#[test]
	fn create_ctl() {
        let mut file = File::open(concat!(env!("CARGO_MANIFEST_DIR"),
                                          "/test/self-signed.badssl.com.cer"))
                           .unwrap();
        let mut cert = vec![];
        file.read_to_end(&mut cert).unwrap();

        let mut store = CertStore::memory().unwrap();
        let cert = store.add_encoded_certificate(&cert).unwrap();

        CtlContext::builder()
        	.certificate(cert)
            .usage("1.3.6.1.4.1.311.2.2.2")
            .encode_and_sign()
            .unwrap();
	}
}<|endoftext|>