<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/. */

//! Servo, the mighty web browser engine from the future.
//!
//! This is a very simple library that wires all of Servo's components
//! together as type `Browser`, along with a generic client
//! implementing the `WindowMethods` trait, to create a working web
//! browser.
//!
//! The `Browser` type is responsible for configuring a
//! `Constellation`, which does the heavy lifting of coordinating all
//! of Servo's internal subsystems, including the `ScriptThread` and the
//! `LayoutThread`, as well maintains the navigation context.
//!
//! The `Browser` is fed events from a generic type that implements the
//! `WindowMethods` trait.

#[cfg(not(target_os = "windows"))]
extern crate gaol;
#[macro_use]
extern crate gleam;

pub extern crate canvas;
pub extern crate canvas_traits;
pub extern crate compositing;
pub extern crate constellation;
pub extern crate devtools;
pub extern crate devtools_traits;
pub extern crate euclid;
pub extern crate gfx;
pub extern crate ipc_channel;
pub extern crate layout_thread;
pub extern crate msg;
pub extern crate net;
pub extern crate net_traits;
pub extern crate profile;
pub extern crate profile_traits;
pub extern crate script;
pub extern crate script_traits;
pub extern crate script_layout_interface;
pub extern crate style;
pub extern crate url;
pub extern crate util;

#[cfg(feature = "webdriver")]
extern crate webdriver_server;

extern crate webrender;
extern crate webrender_traits;

#[cfg(feature = "webdriver")]
fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
    webdriver_server::start_server(port, constellation);
}

#[cfg(not(feature = "webdriver"))]
fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) { }

use compositing::compositor_thread::InitialCompositorState;
use compositing::windowing::WindowEvent;
use compositing::windowing::WindowMethods;
use compositing::{CompositorProxy, IOCompositor};
#[cfg(not(target_os = "windows"))]
use constellation::content_process_sandbox_profile;
use constellation::{Constellation, InitialConstellationState, UnprivilegedPipelineContent};
#[cfg(not(target_os = "windows"))]
use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc::{self, IpcSender};
use net::bluetooth_thread::BluetoothThreadFactory;
use net::image_cache_thread::new_image_cache_thread;
use net::resource_thread::new_resource_threads;
use net_traits::IpcSend;
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use profile::mem as profile_mem;
use profile::time as profile_time;
use profile_traits::mem;
use profile_traits::time;
use script_traits::ConstellationMsg;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use util::opts;
use util::prefs::PREFS;
use util::resource_files::resources_dir_path;

pub use gleam::gl;

/// The in-process interface to Servo.
///
/// It does everything necessary to render the web, primarily
/// orchestrating the interaction between JavaScript, CSS layout,
/// rendering, and the client window.
///
/// Clients create a `Browser` for a given reference-counted type
/// implementing `WindowMethods`, which is the bridge to whatever
/// application Servo is embedded in. Clients then create an event
/// loop to pump messages between the embedding application and
/// various browser components.
pub struct Browser<Window: WindowMethods + 'static> {
    compositor: IOCompositor<Window>,
}

impl<Window> Browser<Window> where Window: WindowMethods + 'static {
    pub fn new(window: Rc<Window>) -> Browser<Window> {
        // Global configuration options, parsed from the command line.
        let opts = opts::get();

        script::init();

        // Get both endpoints of a special channel for communication between
        // the client window and the compositor. This channel is unique because
        // messages to client may need to pump a platform-specific event loop
        // to deliver the message.
        let (compositor_proxy, compositor_receiver) =
            window.create_compositor_channel();
        let supports_clipboard = window.supports_clipboard();
        let time_profiler_chan = profile_time::Profiler::create(&opts.time_profiling,
                                                                opts.time_profiler_trace_path.clone());
        let mem_profiler_chan = profile_mem::Profiler::create(opts.mem_profiler_period);
        let devtools_chan = opts.devtools_port.map(|port| {
            devtools::start_server(port)
        });

        let (webrender, webrender_api_sender) = if opts::get().use_webrender {
            let mut resource_path = resources_dir_path();
            resource_path.push("shaders");

            // TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up!
            let scale_factor = window.scale_factor().get();
            let device_pixel_ratio = match opts.device_pixels_per_px {
                Some(device_pixels_per_px) => device_pixels_per_px,
                None => match opts.output_file {
                    Some(_) => 1.0,
                    None => scale_factor,
                }
            };

            let (webrender, webrender_sender) =
                webrender::Renderer::new(webrender::RendererOptions {
                    device_pixel_ratio: device_pixel_ratio,
                    resource_path: resource_path,
                    enable_aa: opts.enable_text_antialiasing,
                    enable_msaa: opts.use_msaa,
                    enable_profiler: opts.webrender_stats,
                });
            (Some(webrender), Some(webrender_sender))
        } else {
            (None, None)
        };

        // Create the constellation, which maintains the engine
        // pipelines, including the script and layout threads, as well
        // as the navigation context.
        let constellation_chan = create_constellation(opts.clone(),
                                                      compositor_proxy.clone_compositor_proxy(),
                                                      time_profiler_chan.clone(),
                                                      mem_profiler_chan.clone(),
                                                      devtools_chan,
                                                      supports_clipboard,
                                                      webrender_api_sender.clone());

        if cfg!(feature = "webdriver") {
            if let Some(port) = opts.webdriver_port {
                webdriver(port, constellation_chan.clone());
            }
        }

        // The compositor coordinates with the client window to create the final
        // rendered page and display it somewhere.
        let compositor = IOCompositor::create(window, InitialCompositorState {
            sender: compositor_proxy,
            receiver: compositor_receiver,
            constellation_chan: constellation_chan,
            time_profiler_chan: time_profiler_chan,
            mem_profiler_chan: mem_profiler_chan,
            webrender: webrender,
            webrender_api_sender: webrender_api_sender,
        });

        Browser {
            compositor: compositor,
        }
    }

    pub fn handle_events(&mut self, events: Vec<WindowEvent>) -> bool {
        self.compositor.handle_events(events)
    }

    pub fn repaint_synchronously(&mut self) {
        self.compositor.repaint_synchronously()
    }

    pub fn pinch_zoom_level(&self) -> f32 {
        self.compositor.pinch_zoom_level()
    }

    pub fn request_title_for_main_frame(&self) {
        self.compositor.title_for_main_frame()
    }
}

fn create_constellation(opts: opts::Opts,
                        compositor_proxy: Box<CompositorProxy + Send>,
                        time_profiler_chan: time::ProfilerChan,
                        mem_profiler_chan: mem::ProfilerChan,
                        devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
                        supports_clipboard: bool,
                        webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
    let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();

    let (public_resource_threads, private_resource_threads) =
        new_resource_threads(opts.user_agent.clone(),
                             devtools_chan.clone(),
                             time_profiler_chan.clone());
    let image_cache_thread = new_image_cache_thread(public_resource_threads.sender(),
                                                    webrender_api_sender.as_ref().map(|wr| wr.create_api()));
    let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(),
                                                 webrender_api_sender.as_ref().map(|wr| wr.create_api()));

    let initial_state = InitialConstellationState {
        compositor_proxy: compositor_proxy,
        devtools_chan: devtools_chan,
        bluetooth_thread: bluetooth_thread,
        image_cache_thread: image_cache_thread,
        font_cache_thread: font_cache_thread,
        public_resource_threads: public_resource_threads,
        private_resource_threads: private_resource_threads,
        time_profiler_chan: time_profiler_chan,
        mem_profiler_chan: mem_profiler_chan,
        supports_clipboard: supports_clipboard,
        webrender_api_sender: webrender_api_sender,
    };
    let constellation_chan =
        Constellation::<script_layout_interface::message::Msg,
                        layout_thread::LayoutThread,
                        script::script_thread::ScriptThread>::start(initial_state);

    // Send the URL command to the constellation.
    match opts.url {
        Some(url) => {
            constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
        },
        None => ()
    };

    constellation_chan
}

/// Content process entry point.
pub fn run_content_process(token: String) {
    let (unprivileged_content_sender, unprivileged_content_receiver) =
        ipc::channel::<UnprivilegedPipelineContent>().unwrap();
    let connection_bootstrap: IpcSender<IpcSender<UnprivilegedPipelineContent>> =
        IpcSender::connect(token).unwrap();
    connection_bootstrap.send(unprivileged_content_sender).unwrap();

    let unprivileged_content = unprivileged_content_receiver.recv().unwrap();
    opts::set_defaults(unprivileged_content.opts());
    PREFS.extend(unprivileged_content.prefs());

    // Enter the sandbox if necessary.
    if opts::get().sandbox {
       create_sandbox();
    }

    script::init();

    unprivileged_content.start_all::<script_layout_interface::message::Msg,
                                     layout_thread::LayoutThread,
                                     script::script_thread::ScriptThread>(true);
}

// This is a workaround for https://github.com/rust-lang/rust/pull/30175 until
// https://github.com/lfairy/rust-errno/pull/5 lands, and should be removed once
// we update Servo with the rust-errno crate.
#[cfg(target_os = "android")]
#[no_mangle]
pub unsafe extern fn __errno_location() -> *mut i32 {
    extern { fn __errno() -> *mut i32; }
    __errno()
}

#[cfg(not(target_os = "windows"))]
fn create_sandbox() {
    ChildSandbox::new(content_process_sandbox_profile()).activate()
        .expect("Failed to activate sandbox!");
}

#[cfg(target_os = "windows")]
fn create_sandbox() {
    panic!("Sandboxing is not supported on Windows.");
}
<commit_msg>Auto merge of #12240 - perlun:fix/use-if-let, r=ConnorGBrewster<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/. */

//! Servo, the mighty web browser engine from the future.
//!
//! This is a very simple library that wires all of Servo's components
//! together as type `Browser`, along with a generic client
//! implementing the `WindowMethods` trait, to create a working web
//! browser.
//!
//! The `Browser` type is responsible for configuring a
//! `Constellation`, which does the heavy lifting of coordinating all
//! of Servo's internal subsystems, including the `ScriptThread` and the
//! `LayoutThread`, as well maintains the navigation context.
//!
//! The `Browser` is fed events from a generic type that implements the
//! `WindowMethods` trait.

#[cfg(not(target_os = "windows"))]
extern crate gaol;
#[macro_use]
extern crate gleam;

pub extern crate canvas;
pub extern crate canvas_traits;
pub extern crate compositing;
pub extern crate constellation;
pub extern crate devtools;
pub extern crate devtools_traits;
pub extern crate euclid;
pub extern crate gfx;
pub extern crate ipc_channel;
pub extern crate layout_thread;
pub extern crate msg;
pub extern crate net;
pub extern crate net_traits;
pub extern crate profile;
pub extern crate profile_traits;
pub extern crate script;
pub extern crate script_traits;
pub extern crate script_layout_interface;
pub extern crate style;
pub extern crate url;
pub extern crate util;

#[cfg(feature = "webdriver")]
extern crate webdriver_server;

extern crate webrender;
extern crate webrender_traits;

#[cfg(feature = "webdriver")]
fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
    webdriver_server::start_server(port, constellation);
}

#[cfg(not(feature = "webdriver"))]
fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) { }

use compositing::compositor_thread::InitialCompositorState;
use compositing::windowing::WindowEvent;
use compositing::windowing::WindowMethods;
use compositing::{CompositorProxy, IOCompositor};
#[cfg(not(target_os = "windows"))]
use constellation::content_process_sandbox_profile;
use constellation::{Constellation, InitialConstellationState, UnprivilegedPipelineContent};
#[cfg(not(target_os = "windows"))]
use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc::{self, IpcSender};
use net::bluetooth_thread::BluetoothThreadFactory;
use net::image_cache_thread::new_image_cache_thread;
use net::resource_thread::new_resource_threads;
use net_traits::IpcSend;
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use profile::mem as profile_mem;
use profile::time as profile_time;
use profile_traits::mem;
use profile_traits::time;
use script_traits::ConstellationMsg;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use util::opts;
use util::prefs::PREFS;
use util::resource_files::resources_dir_path;

pub use gleam::gl;

/// The in-process interface to Servo.
///
/// It does everything necessary to render the web, primarily
/// orchestrating the interaction between JavaScript, CSS layout,
/// rendering, and the client window.
///
/// Clients create a `Browser` for a given reference-counted type
/// implementing `WindowMethods`, which is the bridge to whatever
/// application Servo is embedded in. Clients then create an event
/// loop to pump messages between the embedding application and
/// various browser components.
pub struct Browser<Window: WindowMethods + 'static> {
    compositor: IOCompositor<Window>,
}

impl<Window> Browser<Window> where Window: WindowMethods + 'static {
    pub fn new(window: Rc<Window>) -> Browser<Window> {
        // Global configuration options, parsed from the command line.
        let opts = opts::get();

        script::init();

        // Get both endpoints of a special channel for communication between
        // the client window and the compositor. This channel is unique because
        // messages to client may need to pump a platform-specific event loop
        // to deliver the message.
        let (compositor_proxy, compositor_receiver) =
            window.create_compositor_channel();
        let supports_clipboard = window.supports_clipboard();
        let time_profiler_chan = profile_time::Profiler::create(&opts.time_profiling,
                                                                opts.time_profiler_trace_path.clone());
        let mem_profiler_chan = profile_mem::Profiler::create(opts.mem_profiler_period);
        let devtools_chan = opts.devtools_port.map(|port| {
            devtools::start_server(port)
        });

        let (webrender, webrender_api_sender) = if opts::get().use_webrender {
            let mut resource_path = resources_dir_path();
            resource_path.push("shaders");

            // TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up!
            let scale_factor = window.scale_factor().get();
            let device_pixel_ratio = match opts.device_pixels_per_px {
                Some(device_pixels_per_px) => device_pixels_per_px,
                None => match opts.output_file {
                    Some(_) => 1.0,
                    None => scale_factor,
                }
            };

            let (webrender, webrender_sender) =
                webrender::Renderer::new(webrender::RendererOptions {
                    device_pixel_ratio: device_pixel_ratio,
                    resource_path: resource_path,
                    enable_aa: opts.enable_text_antialiasing,
                    enable_msaa: opts.use_msaa,
                    enable_profiler: opts.webrender_stats,
                });
            (Some(webrender), Some(webrender_sender))
        } else {
            (None, None)
        };

        // Create the constellation, which maintains the engine
        // pipelines, including the script and layout threads, as well
        // as the navigation context.
        let constellation_chan = create_constellation(opts.clone(),
                                                      compositor_proxy.clone_compositor_proxy(),
                                                      time_profiler_chan.clone(),
                                                      mem_profiler_chan.clone(),
                                                      devtools_chan,
                                                      supports_clipboard,
                                                      webrender_api_sender.clone());

        if cfg!(feature = "webdriver") {
            if let Some(port) = opts.webdriver_port {
                webdriver(port, constellation_chan.clone());
            }
        }

        // The compositor coordinates with the client window to create the final
        // rendered page and display it somewhere.
        let compositor = IOCompositor::create(window, InitialCompositorState {
            sender: compositor_proxy,
            receiver: compositor_receiver,
            constellation_chan: constellation_chan,
            time_profiler_chan: time_profiler_chan,
            mem_profiler_chan: mem_profiler_chan,
            webrender: webrender,
            webrender_api_sender: webrender_api_sender,
        });

        Browser {
            compositor: compositor,
        }
    }

    pub fn handle_events(&mut self, events: Vec<WindowEvent>) -> bool {
        self.compositor.handle_events(events)
    }

    pub fn repaint_synchronously(&mut self) {
        self.compositor.repaint_synchronously()
    }

    pub fn pinch_zoom_level(&self) -> f32 {
        self.compositor.pinch_zoom_level()
    }

    pub fn request_title_for_main_frame(&self) {
        self.compositor.title_for_main_frame()
    }
}

fn create_constellation(opts: opts::Opts,
                        compositor_proxy: Box<CompositorProxy + Send>,
                        time_profiler_chan: time::ProfilerChan,
                        mem_profiler_chan: mem::ProfilerChan,
                        devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
                        supports_clipboard: bool,
                        webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
    let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();

    let (public_resource_threads, private_resource_threads) =
        new_resource_threads(opts.user_agent.clone(),
                             devtools_chan.clone(),
                             time_profiler_chan.clone());
    let image_cache_thread = new_image_cache_thread(public_resource_threads.sender(),
                                                    webrender_api_sender.as_ref().map(|wr| wr.create_api()));
    let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(),
                                                 webrender_api_sender.as_ref().map(|wr| wr.create_api()));

    let initial_state = InitialConstellationState {
        compositor_proxy: compositor_proxy,
        devtools_chan: devtools_chan,
        bluetooth_thread: bluetooth_thread,
        image_cache_thread: image_cache_thread,
        font_cache_thread: font_cache_thread,
        public_resource_threads: public_resource_threads,
        private_resource_threads: private_resource_threads,
        time_profiler_chan: time_profiler_chan,
        mem_profiler_chan: mem_profiler_chan,
        supports_clipboard: supports_clipboard,
        webrender_api_sender: webrender_api_sender,
    };
    let constellation_chan =
        Constellation::<script_layout_interface::message::Msg,
                        layout_thread::LayoutThread,
                        script::script_thread::ScriptThread>::start(initial_state);

    if let Some(url) = opts.url {
        constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
    };

    constellation_chan
}

/// Content process entry point.
pub fn run_content_process(token: String) {
    let (unprivileged_content_sender, unprivileged_content_receiver) =
        ipc::channel::<UnprivilegedPipelineContent>().unwrap();
    let connection_bootstrap: IpcSender<IpcSender<UnprivilegedPipelineContent>> =
        IpcSender::connect(token).unwrap();
    connection_bootstrap.send(unprivileged_content_sender).unwrap();

    let unprivileged_content = unprivileged_content_receiver.recv().unwrap();
    opts::set_defaults(unprivileged_content.opts());
    PREFS.extend(unprivileged_content.prefs());

    // Enter the sandbox if necessary.
    if opts::get().sandbox {
       create_sandbox();
    }

    script::init();

    unprivileged_content.start_all::<script_layout_interface::message::Msg,
                                     layout_thread::LayoutThread,
                                     script::script_thread::ScriptThread>(true);
}

// This is a workaround for https://github.com/rust-lang/rust/pull/30175 until
// https://github.com/lfairy/rust-errno/pull/5 lands, and should be removed once
// we update Servo with the rust-errno crate.
#[cfg(target_os = "android")]
#[no_mangle]
pub unsafe extern fn __errno_location() -> *mut i32 {
    extern { fn __errno() -> *mut i32; }
    __errno()
}

#[cfg(not(target_os = "windows"))]
fn create_sandbox() {
    ChildSandbox::new(content_process_sandbox_profile()).activate()
        .expect("Failed to activate sandbox!");
}

#[cfg(target_os = "windows")]
fn create_sandbox() {
    panic!("Sandboxing is not supported on Windows.");
}
<|endoftext|>


<commit_before>use anyhow::Error;

use crate::util::errors::{CargoResult, HttpNot200};
use crate::util::Config;

pub struct Retry<'a> {
    config: &'a Config,
    remaining: u32,
}

impl<'a> Retry<'a> {
    pub fn new(config: &'a Config) -> CargoResult<Retry<'a>> {
        Ok(Retry {
            config,
            remaining: config.net_config()?.retry.unwrap_or(2),
        })
    }

    pub fn r#try<T>(&mut self, f: impl FnOnce() -> CargoResult<T>) -> CargoResult<Option<T>> {
        match f() {
            Err(ref e) if maybe_spurious(e) && self.remaining > 0 => {
                let msg = format!(
                    "spurious network error ({} tries remaining): {}",
                    self.remaining,
                    e.root_cause(),
                );
                self.config.shell().warn(msg)?;
                self.remaining -= 1;
                Ok(None)
            }
            other => other.map(Some),
        }
    }
}

fn maybe_spurious(err: &Error) -> bool {
    if let Some(git_err) = err.downcast_ref::<git2::Error>() {
        match git_err.class() {
            git2::ErrorClass::Net | git2::ErrorClass::Os | git2::ErrorClass::Zlib => return true,
            _ => (),
        }
    }
    if let Some(curl_err) = err.downcast_ref::<curl::Error>() {
        if curl_err.is_couldnt_connect()
            || curl_err.is_couldnt_resolve_proxy()
            || curl_err.is_couldnt_resolve_host()
            || curl_err.is_operation_timedout()
            || curl_err.is_recv_error()
            || curl_err.is_http2_error()
            || curl_err.is_http2_stream_error()
            || curl_err.is_ssl_connect_error()
            || curl_err.is_partial_file()
        {
            return true;
        }
    }
    if let Some(not_200) = err.downcast_ref::<HttpNot200>() {
        if 500 <= not_200.code && not_200.code < 600 {
            return true;
        }
    }
    false
}

/// Wrapper method for network call retry logic.
///
/// Retry counts provided by Config object `net.retry`. Config shell outputs
/// a warning on per retry.
///
/// Closure must return a `CargoResult`.
///
/// # Examples
///
/// ```
/// # use crate::cargo::util::{CargoResult, Config};
/// # let download_something = || return Ok(());
/// # let config = Config::default().unwrap();
/// use cargo::util::network;
/// let cargo_result = network::with_retry(&config, || download_something());
/// ```
pub fn with_retry<T, F>(config: &Config, mut callback: F) -> CargoResult<T>
where
    F: FnMut() -> CargoResult<T>,
{
    let mut retry = Retry::new(config)?;
    loop {
        if let Some(ret) = retry.r#try(&mut callback)? {
            return Ok(ret);
        }
    }
}

#[test]
fn with_retry_repeats_the_call_then_works() {
    use crate::core::Shell;

    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
    let error1 = HttpNot200 {
        code: 501,
        url: "Uri".to_string(),
    }
    .into();
    let error2 = HttpNot200 {
        code: 502,
        url: "Uri".to_string(),
    }
    .into();
    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
    let config = Config::default().unwrap();
    *config.shell() = Shell::from_write(Box::new(Vec::new()));
    let result = with_retry(&config, || results.pop().unwrap());
    assert!(result.is_ok())
}

#[test]
fn with_retry_finds_nested_spurious_errors() {
    use crate::core::Shell;

    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
    //String error messages are not considered spurious
    let error1 = anyhow::Error::from(HttpNot200 {
        code: 501,
        url: "Uri".to_string(),
    });
    let error1 = anyhow::Error::from(error1.context("A non-spurious wrapping err"));
    let error2 = anyhow::Error::from(HttpNot200 {
        code: 502,
        url: "Uri".to_string(),
    });
    let error2 = anyhow::Error::from(error2.context("A second chained error"));
    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
    let config = Config::default().unwrap();
    *config.shell() = Shell::from_write(Box::new(Vec::new()));
    let result = with_retry(&config, || results.pop().unwrap());
    assert!(result.is_ok())
}

#[test]
fn curle_http2_stream_is_spurious() {
    let code = curl_sys::CURLE_HTTP2_STREAM;
    let err = curl::Error::new(code);
    assert!(maybe_spurious(&err.into()));
}
<commit_msg>Auto merge of #8553 - alexcrichton:more-maybe-spurious, r=ehuss<commit_after>use anyhow::Error;

use crate::util::errors::{CargoResult, HttpNot200};
use crate::util::Config;

pub struct Retry<'a> {
    config: &'a Config,
    remaining: u32,
}

impl<'a> Retry<'a> {
    pub fn new(config: &'a Config) -> CargoResult<Retry<'a>> {
        Ok(Retry {
            config,
            remaining: config.net_config()?.retry.unwrap_or(2),
        })
    }

    pub fn r#try<T>(&mut self, f: impl FnOnce() -> CargoResult<T>) -> CargoResult<Option<T>> {
        match f() {
            Err(ref e) if maybe_spurious(e) && self.remaining > 0 => {
                let msg = format!(
                    "spurious network error ({} tries remaining): {}",
                    self.remaining,
                    e.root_cause(),
                );
                self.config.shell().warn(msg)?;
                self.remaining -= 1;
                Ok(None)
            }
            other => other.map(Some),
        }
    }
}

fn maybe_spurious(err: &Error) -> bool {
    if let Some(git_err) = err.downcast_ref::<git2::Error>() {
        match git_err.class() {
            git2::ErrorClass::Net
            | git2::ErrorClass::Os
            | git2::ErrorClass::Zlib
            | git2::ErrorClass::Http => return true,
            _ => (),
        }
    }
    if let Some(curl_err) = err.downcast_ref::<curl::Error>() {
        if curl_err.is_couldnt_connect()
            || curl_err.is_couldnt_resolve_proxy()
            || curl_err.is_couldnt_resolve_host()
            || curl_err.is_operation_timedout()
            || curl_err.is_recv_error()
            || curl_err.is_http2_error()
            || curl_err.is_http2_stream_error()
            || curl_err.is_ssl_connect_error()
            || curl_err.is_partial_file()
        {
            return true;
        }
    }
    if let Some(not_200) = err.downcast_ref::<HttpNot200>() {
        if 500 <= not_200.code && not_200.code < 600 {
            return true;
        }
    }
    false
}

/// Wrapper method for network call retry logic.
///
/// Retry counts provided by Config object `net.retry`. Config shell outputs
/// a warning on per retry.
///
/// Closure must return a `CargoResult`.
///
/// # Examples
///
/// ```
/// # use crate::cargo::util::{CargoResult, Config};
/// # let download_something = || return Ok(());
/// # let config = Config::default().unwrap();
/// use cargo::util::network;
/// let cargo_result = network::with_retry(&config, || download_something());
/// ```
pub fn with_retry<T, F>(config: &Config, mut callback: F) -> CargoResult<T>
where
    F: FnMut() -> CargoResult<T>,
{
    let mut retry = Retry::new(config)?;
    loop {
        if let Some(ret) = retry.r#try(&mut callback)? {
            return Ok(ret);
        }
    }
}

#[test]
fn with_retry_repeats_the_call_then_works() {
    use crate::core::Shell;

    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
    let error1 = HttpNot200 {
        code: 501,
        url: "Uri".to_string(),
    }
    .into();
    let error2 = HttpNot200 {
        code: 502,
        url: "Uri".to_string(),
    }
    .into();
    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
    let config = Config::default().unwrap();
    *config.shell() = Shell::from_write(Box::new(Vec::new()));
    let result = with_retry(&config, || results.pop().unwrap());
    assert!(result.is_ok())
}

#[test]
fn with_retry_finds_nested_spurious_errors() {
    use crate::core::Shell;

    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
    //String error messages are not considered spurious
    let error1 = anyhow::Error::from(HttpNot200 {
        code: 501,
        url: "Uri".to_string(),
    });
    let error1 = anyhow::Error::from(error1.context("A non-spurious wrapping err"));
    let error2 = anyhow::Error::from(HttpNot200 {
        code: 502,
        url: "Uri".to_string(),
    });
    let error2 = anyhow::Error::from(error2.context("A second chained error"));
    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
    let config = Config::default().unwrap();
    *config.shell() = Shell::from_write(Box::new(Vec::new()));
    let result = with_retry(&config, || results.pop().unwrap());
    assert!(result.is_ok())
}

#[test]
fn curle_http2_stream_is_spurious() {
    let code = curl_sys::CURLE_HTTP2_STREAM;
    let err = curl::Error::new(code);
    assert!(maybe_spurious(&err.into()));
}
<|endoftext|>


<commit_before>use hir::{
    db::DefDatabase,
    diagnostics::{Diagnostic, DiagnosticCode},
    InFile,
};
use ide_db::{
    base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt},
    source_change::SourceChange,
    RootDatabase,
};
use syntax::{
    ast::{self, ModuleItemOwner, NameOwner},
    AstNode, SyntaxNodePtr,
};
use text_edit::TextEdit;

use crate::Fix;

use super::fixes::DiagnosticWithFix;

#[derive(Debug)]
pub(crate) struct UnlinkedFile {
    pub(crate) file_id: FileId,
    pub(crate) node: SyntaxNodePtr,
}

impl Diagnostic for UnlinkedFile {
    fn code(&self) -> DiagnosticCode {
        DiagnosticCode("unlinked-file")
    }

    fn message(&self) -> String {
        "file not included in module tree".to_string()
    }

    fn display_source(&self) -> InFile<SyntaxNodePtr> {
        InFile::new(self.file_id.into(), self.node.clone())
    }

    fn as_any(&self) -> &(dyn std::any::Any + Send + 'static) {
        self
    }
}

impl DiagnosticWithFix for UnlinkedFile {
    fn fix(&self, sema: &hir::Semantics<RootDatabase>) -> Option<Fix> {
        // If there's an existing module that could add a `mod` item to include the unlinked file,
        // suggest that as a fix.

        let source_root = sema.db.source_root(sema.db.file_source_root(self.file_id));
        let our_path = source_root.path_for_file(&self.file_id)?;
        let module_name = our_path.name_and_extension()?.0;

        // Candidates to look for:
        // - `mod.rs` in the same folder
        //   - we also check `main.rs` and `lib.rs`
        // - `$dir.rs` in the parent folder, where `$dir` is the directory containing `self.file_id`
        let parent = our_path.parent()?;
        let mut paths =
            vec![parent.join("mod.rs")?, parent.join("main.rs")?, parent.join("lib.rs")?];

        // `submod/bla.rs` -> `submod.rs`
        if let Some(newmod) = (|| {
            let name = parent.name_and_extension()?.0;
            parent.parent()?.join(&format!("{}.rs", name))
        })() {
            paths.push(newmod);
        }

        for path in &paths {
            if let Some(parent_id) = source_root.file_for_path(path) {
                for krate in sema.db.relevant_crates(*parent_id).iter() {
                    let crate_def_map = sema.db.crate_def_map(*krate);
                    for (_, module) in crate_def_map.modules() {
                        if module.origin.is_inline() {
                            // We don't handle inline `mod parent {}`s, they use different paths.
                            continue;
                        }

                        if module.origin.file_id() == Some(*parent_id) {
                            return make_fix(sema.db, *parent_id, module_name, self.file_id);
                        }
                    }
                }
            }
        }

        None
    }
}

fn make_fix(
    db: &RootDatabase,
    parent_file_id: FileId,
    new_mod_name: &str,
    added_file_id: FileId,
) -> Option<Fix> {
    fn is_outline_mod(item: &ast::Item) -> bool {
        matches!(item, ast::Item::Module(m) if m.item_list().is_none())
    }

    let mod_decl = format!("mod {};", new_mod_name);
    let ast: ast::SourceFile = db.parse(parent_file_id).tree();

    let mut builder = TextEdit::builder();

    // If there's an existing `mod m;` statement matching the new one, don't emit a fix (it's
    // probably `#[cfg]`d out).
    for item in ast.items() {
        if let ast::Item::Module(m) = item {
            if let Some(name) = m.name() {
                if m.item_list().is_none() && name.to_string() == new_mod_name {
                    cov_mark::hit!(unlinked_file_skip_fix_when_mod_already_exists);
                    return None;
                }
            }
        }
    }

    // If there are existing `mod m;` items, append after them (after the first group of them, rather).
    match ast
        .items()
        .skip_while(|item| !is_outline_mod(item))
        .take_while(|item| is_outline_mod(item))
        .last()
    {
        Some(last) => {
            cov_mark::hit!(unlinked_file_append_to_existing_mods);
            builder.insert(last.syntax().text_range().end(), format!("\n{}", mod_decl));
        }
        None => {
            // Prepend before the first item in the file.
            match ast.items().next() {
                Some(item) => {
                    cov_mark::hit!(unlinked_file_prepend_before_first_item);
                    builder.insert(item.syntax().text_range().start(), format!("{}\n\n", mod_decl));
                }
                None => {
                    // No items in the file, so just append at the end.
                    cov_mark::hit!(unlinked_file_empty_file);
                    builder.insert(ast.syntax().text_range().end(), format!("{}\n", mod_decl));
                }
            }
        }
    }

    let edit = builder.finish();
    let trigger_range = db.parse(added_file_id).tree().syntax().text_range();
    Some(Fix::new(
        &format!("Insert `{}`", mod_decl),
        SourceChange::from_text_edit(parent_file_id, edit),
        trigger_range,
    ))
}
<commit_msg>Add module comment<commit_after>//! Diagnostic emitted for files that aren't part of any crate.

use hir::{
    db::DefDatabase,
    diagnostics::{Diagnostic, DiagnosticCode},
    InFile,
};
use ide_db::{
    base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt},
    source_change::SourceChange,
    RootDatabase,
};
use syntax::{
    ast::{self, ModuleItemOwner, NameOwner},
    AstNode, SyntaxNodePtr,
};
use text_edit::TextEdit;

use crate::Fix;

use super::fixes::DiagnosticWithFix;

#[derive(Debug)]
pub(crate) struct UnlinkedFile {
    pub(crate) file_id: FileId,
    pub(crate) node: SyntaxNodePtr,
}

impl Diagnostic for UnlinkedFile {
    fn code(&self) -> DiagnosticCode {
        DiagnosticCode("unlinked-file")
    }

    fn message(&self) -> String {
        "file not included in module tree".to_string()
    }

    fn display_source(&self) -> InFile<SyntaxNodePtr> {
        InFile::new(self.file_id.into(), self.node.clone())
    }

    fn as_any(&self) -> &(dyn std::any::Any + Send + 'static) {
        self
    }
}

impl DiagnosticWithFix for UnlinkedFile {
    fn fix(&self, sema: &hir::Semantics<RootDatabase>) -> Option<Fix> {
        // If there's an existing module that could add a `mod` item to include the unlinked file,
        // suggest that as a fix.

        let source_root = sema.db.source_root(sema.db.file_source_root(self.file_id));
        let our_path = source_root.path_for_file(&self.file_id)?;
        let module_name = our_path.name_and_extension()?.0;

        // Candidates to look for:
        // - `mod.rs` in the same folder
        //   - we also check `main.rs` and `lib.rs`
        // - `$dir.rs` in the parent folder, where `$dir` is the directory containing `self.file_id`
        let parent = our_path.parent()?;
        let mut paths =
            vec![parent.join("mod.rs")?, parent.join("main.rs")?, parent.join("lib.rs")?];

        // `submod/bla.rs` -> `submod.rs`
        if let Some(newmod) = (|| {
            let name = parent.name_and_extension()?.0;
            parent.parent()?.join(&format!("{}.rs", name))
        })() {
            paths.push(newmod);
        }

        for path in &paths {
            if let Some(parent_id) = source_root.file_for_path(path) {
                for krate in sema.db.relevant_crates(*parent_id).iter() {
                    let crate_def_map = sema.db.crate_def_map(*krate);
                    for (_, module) in crate_def_map.modules() {
                        if module.origin.is_inline() {
                            // We don't handle inline `mod parent {}`s, they use different paths.
                            continue;
                        }

                        if module.origin.file_id() == Some(*parent_id) {
                            return make_fix(sema.db, *parent_id, module_name, self.file_id);
                        }
                    }
                }
            }
        }

        None
    }
}

fn make_fix(
    db: &RootDatabase,
    parent_file_id: FileId,
    new_mod_name: &str,
    added_file_id: FileId,
) -> Option<Fix> {
    fn is_outline_mod(item: &ast::Item) -> bool {
        matches!(item, ast::Item::Module(m) if m.item_list().is_none())
    }

    let mod_decl = format!("mod {};", new_mod_name);
    let ast: ast::SourceFile = db.parse(parent_file_id).tree();

    let mut builder = TextEdit::builder();

    // If there's an existing `mod m;` statement matching the new one, don't emit a fix (it's
    // probably `#[cfg]`d out).
    for item in ast.items() {
        if let ast::Item::Module(m) = item {
            if let Some(name) = m.name() {
                if m.item_list().is_none() && name.to_string() == new_mod_name {
                    cov_mark::hit!(unlinked_file_skip_fix_when_mod_already_exists);
                    return None;
                }
            }
        }
    }

    // If there are existing `mod m;` items, append after them (after the first group of them, rather).
    match ast
        .items()
        .skip_while(|item| !is_outline_mod(item))
        .take_while(|item| is_outline_mod(item))
        .last()
    {
        Some(last) => {
            cov_mark::hit!(unlinked_file_append_to_existing_mods);
            builder.insert(last.syntax().text_range().end(), format!("\n{}", mod_decl));
        }
        None => {
            // Prepend before the first item in the file.
            match ast.items().next() {
                Some(item) => {
                    cov_mark::hit!(unlinked_file_prepend_before_first_item);
                    builder.insert(item.syntax().text_range().start(), format!("{}\n\n", mod_decl));
                }
                None => {
                    // No items in the file, so just append at the end.
                    cov_mark::hit!(unlinked_file_empty_file);
                    builder.insert(ast.syntax().text_range().end(), format!("{}\n", mod_decl));
                }
            }
        }
    }

    let edit = builder.finish();
    let trigger_range = db.parse(added_file_id).tree().syntax().text_range();
    Some(Fix::new(
        &format!("Insert `{}`", mod_decl),
        SourceChange::from_text_edit(parent_file_id, edit),
        trigger_range,
    ))
}
<|endoftext|>


<commit_before>
use glium::{Program, Surface};
use glium::texture::{Texture2dArray};
use glium::VertexBuffer;
use glium::index;
use glutin;

use render::shader::ShaderPair;
use render::texture_array::TextureDirectory;

use input;
use HashMap;
use input::InputState;
use color::{rgb};

use std::sync::mpsc::{channel, Receiver};

use notify::{RecommendedWatcher, Watcher, RecursiveMode, RawEvent};

use super::window;
use super::program;
use render::command::*;
use render::command::Command::*;
use render::{Dimensions, Seconds};
use render::vertex::Vertex;

use time;

pub trait Application {
    fn new(&mut self);
    fn render(&mut self, input:&InputState, dimensions:Dimensions, delta_time: Seconds) -> Vec<Command>; // sizing (window) ?
}

pub fn run_app<T : Application>(mut app:T, shader_pair:ShaderPair, texture_directory: TextureDirectory, initial_dimensions: (u32, u32)) {
    println!("shader pair -> {:?}", shader_pair);

    app.new();

    let display = window::create_window("mah window", true, initial_dimensions);

    let (tx, notifier_rx) = channel::<RawEvent>();
    // , Duration::from_secs(0)
    let mut watcher : RecommendedWatcher = Watcher::new_raw(tx).expect("a watcher");
    watcher.watch(&shader_pair.vertex_path, RecursiveMode::Recursive).expect("watching shader vertex path");
    watcher.watch(&shader_pair.fragment_path, RecursiveMode::Recursive).expect("watching shader fragment path");
    watcher.watch(&texture_directory.path, RecursiveMode::Recursive).expect("watching texture directory path");

    let mut input_state = InputState::default();

    let mut program : Option<Program> = None;
    let mut texture_array : Option<Texture2dArray> = None;
    let mut vertex_buffers : HashMap<BufferKey, VertexBuffer<Vertex>> = HashMap::default();

    let mut last_time = time::precise_time_ns();

    'main: loop {
        let (reload_program, reload_texture) = check_reload(&notifier_rx, &shader_pair, &texture_directory);

        if reload_program || program.is_none() {
            let program_load_result = shader_pair.load().and_then(|shader_data| shader_data.load(&display));
            println!("program load result -> {:?}", program_load_result);
            program = program_load_result.ok();
        }

        if reload_texture || texture_array.is_none() {
            println!("reload texture");
            let texture_load_result = texture_directory.load().and_then(|texture_data| texture_data.load(&display));
            println!("texture load result -> {:?}", texture_load_result);
            texture_array = texture_load_result.ok();
        }

        let events : Vec<glutin::Event> = display.poll_events().collect();
        input_state = input::produce(&input_state, &events);

        let (width_pixels, height_pixels) = display.get_framebuffer_dimensions();

        let dimensions = Dimensions {
            width_pixels: width_pixels,
            height_pixels:height_pixels,
            scale: 1.0,
        };

        let now  = time::precise_time_ns();
        let delta = ((now - last_time) as f64) / 1000000000.0;
        let commands = app.render(&input_state, dimensions, delta);
        last_time = now;

        if let (&Some(ref pr), &Some(ref tr)) = (&program, &texture_array) {
            let mut target = display.draw();

            let sky_blue = rgb(132, 193, 255);

            target.clear_color_and_depth(sky_blue.float_tup(), 1.0);

            let mut close_after = false;

            for command in commands {
                // println!("received command -> {:?}", command);
                match command {
                    Delete { prefix } => {
                        let keys_to_remove : Vec<String> = vertex_buffers.keys().filter(|k| k.starts_with(&prefix) ).cloned().collect();
                        for key in keys_to_remove.iter() {
                            vertex_buffers.remove(key);
                        }
                    },
                    Update { key, vertices } => {
                        let new_vertex_buffer = VertexBuffer::persistent(&display,&vertices).unwrap();
                        vertex_buffers.insert(key, new_vertex_buffer);
                    },
                    Draw { key, uniforms } => {
                        if let Some(vertex_buffer) = vertex_buffers.get(&key) {
                            let uniforms = uniform! {
                                u_matrix: uniforms.transform,
                                u_texture_array: tr,
                                u_color: uniforms.color.float_raw(),
                                u_alpha_minimum: 0.01_f32,
                            };
                            target.draw(vertex_buffer, &index::NoIndices(index::PrimitiveType::TrianglesList), &pr, &uniforms, &program::opaque_draw_params()).unwrap();
                        } else {
                            // println!("couldnt draw for {:?}", key);
                        }
                    },
                    DrawNew { key , vertices, uniforms } => {
                        let new_vertex_buffer = VertexBuffer::persistent(&display,&vertices).unwrap();

                        let uniforms = uniform! {
                            u_matrix: uniforms.transform,
                            u_texture_array: tr,
                            u_color: uniforms.color.float_raw(),
                            u_alpha_minimum: 0.01_f32,
                        };

                        target.draw(&new_vertex_buffer, &index::NoIndices(index::PrimitiveType::TrianglesList), &pr, &uniforms, &program::opaque_draw_params()).unwrap();

                        if let Some(name) = key {
                            vertex_buffers.insert(name,new_vertex_buffer);
                        }
                    },
                    Close => {
                        close_after = true;
                    },
                }
            }

            // target.draw(&vertex_buffer, &index::NoIndices(index::PrimitiveType::TrianglesList), &rs.program, &uniforms, &opaque_draw_params()).unwrap();
            target.finish().unwrap();

            if close_after {
                break 'main;
            }
        } else {
            use std::{thread, time};
            println!("can't render, we're missing resources");
            let ten_millis = time::Duration::from_millis(100);
            thread::sleep(ten_millis);
        }
    }
}

pub fn check_reload(rx: &Receiver<RawEvent>, shader_pair:&ShaderPair, texture_directory: &TextureDirectory) -> (bool, bool) {
    let mut reload_program = false;
    let mut reload_texture = false;

    'fs: loop {
        match rx.try_recv() {
            Ok(RawEvent { path, op:_, cookie:_ }) => {
                if let Some(p) = path {
                    if shader_pair.contains(&p) {
                        reload_program = true;
                    } else if texture_directory.contains(&p) {
                        reload_texture = true;
                    } else {
                        use std::path;
                        let components: Vec<path::Component> = p.components().collect();
                        println!("fs event {:?} -> {:?}", p, components);
                    }
                }
            },
            Err(_) => break 'fs,
        }
    }

     (reload_program, reload_texture)
}<commit_msg>Fixed up scaling in glium renderer<commit_after>
use glium::{Program, Surface};
use glium::texture::{Texture2dArray};
use glium::VertexBuffer;
use glium::index;
use glutin;

use render::shader::ShaderPair;
use render::texture_array::TextureDirectory;

use input;
use HashMap;
use input::InputState;
use color::{rgb};

use std::sync::mpsc::{channel, Receiver};

use notify::{RecommendedWatcher, Watcher, RecursiveMode, RawEvent};

use super::window;
use super::program;
use render::command::*;
use render::command::Command::*;
use render::{Dimensions, Seconds};
use render::vertex::Vertex;

use time;

pub trait Application {
    fn new(&mut self);
    fn render(&mut self, input:&InputState, dimensions:Dimensions, delta_time: Seconds) -> Vec<Command>; // sizing (window) ?
}

pub fn run_app<T : Application>(mut app:T, shader_pair:ShaderPair, texture_directory: TextureDirectory, initial_dimensions: (u32, u32)) {
    println!("shader pair -> {:?}", shader_pair);

    app.new();

    let display = window::create_window("mah window", true, initial_dimensions);

    let (tx, notifier_rx) = channel::<RawEvent>();
    // , Duration::from_secs(0)
    let mut watcher : RecommendedWatcher = Watcher::new_raw(tx).expect("a watcher");
    watcher.watch(&shader_pair.vertex_path, RecursiveMode::Recursive).expect("watching shader vertex path");
    watcher.watch(&shader_pair.fragment_path, RecursiveMode::Recursive).expect("watching shader fragment path");
    watcher.watch(&texture_directory.path, RecursiveMode::Recursive).expect("watching texture directory path");

    let mut input_state = InputState::default();

    let mut program : Option<Program> = None;
    let mut texture_array : Option<Texture2dArray> = None;
    let mut vertex_buffers : HashMap<BufferKey, VertexBuffer<Vertex>> = HashMap::default();

    let mut last_time = time::precise_time_ns();

    'main: loop {
        let (reload_program, reload_texture) = check_reload(&notifier_rx, &shader_pair, &texture_directory);

        if reload_program || program.is_none() {
            let program_load_result = shader_pair.load().and_then(|shader_data| shader_data.load(&display));
            println!("program load result -> {:?}", program_load_result);
            program = program_load_result.ok();
        }

        if reload_texture || texture_array.is_none() {
            println!("reload texture");
            let texture_load_result = texture_directory.load().and_then(|texture_data| texture_data.load(&display));
            println!("texture load result -> {:?}", texture_load_result);
            texture_array = texture_load_result.ok();
        }

        let events : Vec<glutin::Event> = display.poll_events().collect();
        input_state = input::produce(&input_state, &events);

        let (width_pixels, height_pixels) = display.get_framebuffer_dimensions();

        let scale : f32 = display.get_window().map(|w| w.hidpi_factor()).unwrap_or(1.0);

        let dimensions = Dimensions {
            width_pixels: width_pixels,
            height_pixels:height_pixels,
            scale: scale,
        };

        let now  = time::precise_time_ns();
        let delta = ((now - last_time) as f64) / 1000000000.0;
        let commands = app.render(&input_state, dimensions, delta);
        last_time = now;

        if let (&Some(ref pr), &Some(ref tr)) = (&program, &texture_array) {
            let mut target = display.draw();

            let sky_blue = rgb(132, 193, 255);

            target.clear_color_and_depth(sky_blue.float_tup(), 1.0);

            let mut close_after = false;

            for command in commands {
                // println!("received command -> {:?}", command);
                match command {
                    Delete { prefix } => {
                        let keys_to_remove : Vec<String> = vertex_buffers.keys().filter(|k| k.starts_with(&prefix) ).cloned().collect();
                        for key in keys_to_remove.iter() {
                            vertex_buffers.remove(key);
                        }
                    },
                    Update { key, vertices } => {
                        let new_vertex_buffer = VertexBuffer::persistent(&display,&vertices).unwrap();
                        vertex_buffers.insert(key, new_vertex_buffer);
                    },
                    Draw { key, uniforms } => {
                        if let Some(vertex_buffer) = vertex_buffers.get(&key) {
                            let uniforms = uniform! {
                                u_matrix: uniforms.transform,
                                u_texture_array: tr,
                                u_color: uniforms.color.float_raw(),
                                u_alpha_minimum: 0.01_f32,
                            };
                            target.draw(vertex_buffer, &index::NoIndices(index::PrimitiveType::TrianglesList), &pr, &uniforms, &program::opaque_draw_params()).unwrap();
                        } else {
                            // println!("couldnt draw for {:?}", key);
                        }
                    },
                    DrawNew { key , vertices, uniforms } => {
                        let new_vertex_buffer = VertexBuffer::persistent(&display,&vertices).unwrap();

                        let uniforms = uniform! {
                            u_matrix: uniforms.transform,
                            u_texture_array: tr,
                            u_color: uniforms.color.float_raw(),
                            u_alpha_minimum: 0.01_f32,
                        };

                        target.draw(&new_vertex_buffer, &index::NoIndices(index::PrimitiveType::TrianglesList), &pr, &uniforms, &program::opaque_draw_params()).unwrap();

                        if let Some(name) = key {
                            vertex_buffers.insert(name,new_vertex_buffer);
                        }
                    },
                    Close => {
                        close_after = true;
                    },
                }
            }

            // target.draw(&vertex_buffer, &index::NoIndices(index::PrimitiveType::TrianglesList), &rs.program, &uniforms, &opaque_draw_params()).unwrap();
            target.finish().unwrap();

            if close_after {
                break 'main;
            }
        } else {
            use std::{thread, time};
            println!("can't render, we're missing resources");
            let ten_millis = time::Duration::from_millis(100);
            thread::sleep(ten_millis);
        }
    }
}

pub fn check_reload(rx: &Receiver<RawEvent>, shader_pair:&ShaderPair, texture_directory: &TextureDirectory) -> (bool, bool) {
    let mut reload_program = false;
    let mut reload_texture = false;

    'fs: loop {
        match rx.try_recv() {
            Ok(RawEvent { path, op:_, cookie:_ }) => {
                if let Some(p) = path {
                    if shader_pair.contains(&p) {
                        reload_program = true;
                    } else if texture_directory.contains(&p) {
                        reload_texture = true;
                    } else {
                        use std::path;
                        let components: Vec<path::Component> = p.components().collect();
                        println!("fs event {:?} -> {:?}", p, components);
                    }
                }
            },
            Err(_) => break 'fs,
        }
    }

     (reload_program, reload_texture)
}<|endoftext|>


<commit_before>use errors::crypto::CryptoError;

extern crate openssl;
extern crate int_traits;
use self::int_traits::IntTraits;

use self::openssl::bn::{BigNum, BigNumRef, BigNumContext, MSB_MAYBE_ZERO};
use self::openssl::error::ErrorStack;
use self::openssl::hash::{hash, MessageDigest};
use std::cmp::Ord;
use std::cmp::Ordering;

use std::error::Error;

pub struct BigNumberContext {
    openssl_bn_context: BigNumContext
}

#[derive(Debug)]
pub struct BigNumber {
    openssl_bn: BigNum
}

impl BigNumber {
    pub fn new_context() -> Result<BigNumberContext, CryptoError> {
        let ctx = try!(BigNumContext::new());
        Ok(BigNumberContext {
            openssl_bn_context: ctx
        })
    }

    pub fn new() -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::new());
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn generate_prime(&self, size: usize) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::generate_prime(&mut bn.openssl_bn, size as i32, false, None, None));
        Ok(bn)
    }

    pub fn generate_safe_prime(&self, size: usize) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::generate_prime(&mut bn.openssl_bn, (size + 1) as i32, true, None, None));
        Ok(bn)
    }

    pub fn generate_prime_in_range(&self, start: &BigNumber, end: &BigNumber) -> Result<BigNumber, CryptoError> {
        let mut prime;
        let mut iteration = 0;
        let mut bn_ctx = try!(BigNumber::new_context());
        let sub = try!(end.sub(start));

        loop {
            prime = try!(sub.rand_range());
            prime = try!(prime.add(start));

            if try!(prime.is_prime(Some(&mut bn_ctx))) {
                debug!("Found prime in {} iteration", iteration);
                break;
            }
            iteration += 1;
        }

        Ok(prime)
    }

    pub fn is_prime(&self, ctx: Option<&mut BigNumberContext>) -> Result<bool, CryptoError> {
        let prime_len = try!(self.to_dec()).len();
        let checks = prime_len.log2() as i32;
        match ctx {
            Some(context) => Ok(try!(self.openssl_bn.is_prime(checks, &mut context.openssl_bn_context))),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                Ok(try!(self.openssl_bn.is_prime(checks, &mut ctx.openssl_bn_context)))
            }
        }
    }

    pub fn rand(&self, size: usize) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::rand(&mut bn.openssl_bn, size as i32, MSB_MAYBE_ZERO, false));
        Ok(bn)
    }

    pub fn rand_range(&self) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::rand_range(&self.openssl_bn, &mut bn.openssl_bn));
        Ok(bn)
    }

    pub fn num_bits(&self) -> Result<i32, CryptoError> {
        Ok(self.openssl_bn.num_bits())
    }

    pub fn is_bit_set(&self, n: i32) -> Result<bool, CryptoError> {
        Ok(self.openssl_bn.is_bit_set(n))
    }

    pub fn set_bit(&mut self, n: i32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::set_bit(&mut self.openssl_bn, n));
        Ok(self)
    }

    pub fn from_u32(n: u32) -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::from_u32(n));
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn from_dec(dec: &str) -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::from_dec_str(dec));
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn from_hex(hex: &str) -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::from_hex_str(hex));
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::from_slice(bytes));
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn to_dec(&self) -> Result<String, CryptoError> {
        let result = try!(self.openssl_bn.to_dec_str());
        Ok(result.to_string())
    }

    pub fn to_hex(&self) -> Result<String, CryptoError> {
        let result = try!(self.openssl_bn.to_hex_str());
        Ok(result.to_string())
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        Ok(self.openssl_bn.to_vec())
    }

    pub fn hash(data: &[u8]) -> Result<Vec<u8>, CryptoError> {
        Ok(try!(hash(MessageDigest::sha256(), data)))
    }

    pub fn add(&self, a: &BigNumber) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::checked_add(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn));
        Ok(bn)
    }

    pub fn sub(&self, a: &BigNumber) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::checked_sub(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn));
        Ok(bn)
    }

    pub fn sqr(&self, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::sqr(&mut bn.openssl_bn, &self.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::sqr(&mut bn.openssl_bn, &self.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn mul(&self, a: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::checked_mul(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::checked_mul(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn div(&self, a: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::checked_div(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::checked_div(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn add_word(&mut self, w: u32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::add_word(&mut self.openssl_bn, w));
        Ok(self)
    }

    pub fn sub_word(&mut self, w: u32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::sub_word(&mut self.openssl_bn, w));
        Ok(self)
    }

    pub fn mul_word(&mut self, w: u32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::mul_word(&mut self.openssl_bn, w));
        Ok(self)
    }

    pub fn div_word(&mut self, w: u32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::div_word(&mut self.openssl_bn, w));
        Ok(self)
    }

    pub fn mod_exp(&self, a: &BigNumber, b: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::mod_exp(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &b.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::mod_exp(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &b.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn modulus(&self, a: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::nnmod(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::nnmod(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn exp(&self, a: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::exp(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::exp(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn inverse(&self, n: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::mod_inverse(&mut bn.openssl_bn, &self.openssl_bn, &n.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::mod_inverse(&mut bn.openssl_bn, &self.openssl_bn, &n.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn mod_div(&self, b: &BigNumber, p: &BigNumber) -> Result<BigNumber, CryptoError> {
        //(a*  (1/b mod p) mod p)

        let mut context = try!(BigNumber::new_context());

        let res = try!(
            b
                .inverse(p, Some(&mut context))?
                .mul(&self, Some(&mut context))?
                .modulus(&p, Some(&mut context))
        );
        Ok(res)
    }

    pub fn clone(&self) -> Result<BigNumber, CryptoError> {
        let bytes = try!(self.to_bytes());
        let bn = try!(BigNumber::from_bytes(bytes.as_slice()));
        Ok(bn)
    }
}

impl Ord for BigNumber {
    fn cmp(&self, other: &BigNumber) -> Ordering {
        self.openssl_bn.ucmp(&other.openssl_bn)
    }
}

impl Eq for BigNumber {}

impl PartialOrd for BigNumber {
    fn partial_cmp(&self, other: &BigNumber) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for BigNumber {
    fn eq(&self, other: &BigNumber) -> bool {
        self.openssl_bn == other.openssl_bn
    }
}

impl From<ErrorStack> for CryptoError {
    fn from(err: ErrorStack) -> CryptoError {
        CryptoError::BackendError(err.description().to_string())
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn generate_prime_in_range_works() {
        let bn = BigNumber::new().unwrap();
        let start = bn.rand(250).unwrap();
        let end = bn.rand(300).unwrap();
        let random_prime = bn.generate_prime_in_range(&start, &end).unwrap();
        assert!(start < random_prime);
        assert!(end > random_prime);
    }
}<commit_msg>added logger to test<commit_after>use errors::crypto::CryptoError;

extern crate openssl;
extern crate int_traits;
use self::int_traits::IntTraits;

use self::openssl::bn::{BigNum, BigNumRef, BigNumContext, MSB_MAYBE_ZERO};
use self::openssl::error::ErrorStack;
use self::openssl::hash::{hash, MessageDigest};
use std::cmp::Ord;
use std::cmp::Ordering;

use std::error::Error;

pub struct BigNumberContext {
    openssl_bn_context: BigNumContext
}

#[derive(Debug)]
pub struct BigNumber {
    openssl_bn: BigNum
}

impl BigNumber {
    pub fn new_context() -> Result<BigNumberContext, CryptoError> {
        let ctx = try!(BigNumContext::new());
        Ok(BigNumberContext {
            openssl_bn_context: ctx
        })
    }

    pub fn new() -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::new());
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn generate_prime(&self, size: usize) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::generate_prime(&mut bn.openssl_bn, size as i32, false, None, None));
        Ok(bn)
    }

    pub fn generate_safe_prime(&self, size: usize) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::generate_prime(&mut bn.openssl_bn, (size + 1) as i32, true, None, None));
        Ok(bn)
    }

    pub fn generate_prime_in_range(&self, start: &BigNumber, end: &BigNumber) -> Result<BigNumber, CryptoError> {
        let mut prime;
        let mut iteration = 0;
        let mut bn_ctx = try!(BigNumber::new_context());
        let sub = try!(end.sub(start));

        loop {
            prime = try!(sub.rand_range());
            prime = try!(prime.add(start));

            if try!(prime.is_prime(Some(&mut bn_ctx))) {
                debug!("Found prime in {} iteration", iteration);
                break;
            }
            iteration += 1;
        }

        Ok(prime)
    }

    pub fn is_prime(&self, ctx: Option<&mut BigNumberContext>) -> Result<bool, CryptoError> {
        let prime_len = try!(self.to_dec()).len();
        let checks = prime_len.log2() as i32;
        match ctx {
            Some(context) => Ok(try!(self.openssl_bn.is_prime(checks, &mut context.openssl_bn_context))),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                Ok(try!(self.openssl_bn.is_prime(checks, &mut ctx.openssl_bn_context)))
            }
        }
    }

    pub fn rand(&self, size: usize) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::rand(&mut bn.openssl_bn, size as i32, MSB_MAYBE_ZERO, false));
        Ok(bn)
    }

    pub fn rand_range(&self) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::rand_range(&self.openssl_bn, &mut bn.openssl_bn));
        Ok(bn)
    }

    pub fn num_bits(&self) -> Result<i32, CryptoError> {
        Ok(self.openssl_bn.num_bits())
    }

    pub fn is_bit_set(&self, n: i32) -> Result<bool, CryptoError> {
        Ok(self.openssl_bn.is_bit_set(n))
    }

    pub fn set_bit(&mut self, n: i32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::set_bit(&mut self.openssl_bn, n));
        Ok(self)
    }

    pub fn from_u32(n: u32) -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::from_u32(n));
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn from_dec(dec: &str) -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::from_dec_str(dec));
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn from_hex(hex: &str) -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::from_hex_str(hex));
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNum::from_slice(bytes));
        Ok(BigNumber {
            openssl_bn: bn
        })
    }

    pub fn to_dec(&self) -> Result<String, CryptoError> {
        let result = try!(self.openssl_bn.to_dec_str());
        Ok(result.to_string())
    }

    pub fn to_hex(&self) -> Result<String, CryptoError> {
        let result = try!(self.openssl_bn.to_hex_str());
        Ok(result.to_string())
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        Ok(self.openssl_bn.to_vec())
    }

    pub fn hash(data: &[u8]) -> Result<Vec<u8>, CryptoError> {
        Ok(try!(hash(MessageDigest::sha256(), data)))
    }

    pub fn add(&self, a: &BigNumber) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::checked_add(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn));
        Ok(bn)
    }

    pub fn sub(&self, a: &BigNumber) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        try!(BigNumRef::checked_sub(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn));
        Ok(bn)
    }

    pub fn sqr(&self, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::sqr(&mut bn.openssl_bn, &self.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::sqr(&mut bn.openssl_bn, &self.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn mul(&self, a: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::checked_mul(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::checked_mul(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn div(&self, a: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::checked_div(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::checked_div(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn add_word(&mut self, w: u32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::add_word(&mut self.openssl_bn, w));
        Ok(self)
    }

    pub fn sub_word(&mut self, w: u32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::sub_word(&mut self.openssl_bn, w));
        Ok(self)
    }

    pub fn mul_word(&mut self, w: u32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::mul_word(&mut self.openssl_bn, w));
        Ok(self)
    }

    pub fn div_word(&mut self, w: u32) -> Result<&mut BigNumber, CryptoError> {
        try!(BigNumRef::div_word(&mut self.openssl_bn, w));
        Ok(self)
    }

    pub fn mod_exp(&self, a: &BigNumber, b: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::mod_exp(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &b.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::mod_exp(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &b.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn modulus(&self, a: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::nnmod(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::nnmod(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn exp(&self, a: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::exp(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::exp(&mut bn.openssl_bn, &self.openssl_bn, &a.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn inverse(&self, n: &BigNumber, ctx: Option<&mut BigNumberContext>) -> Result<BigNumber, CryptoError> {
        let mut bn = try!(BigNumber::new());
        match ctx {
            Some(context) => try!(BigNumRef::mod_inverse(&mut bn.openssl_bn, &self.openssl_bn, &n.openssl_bn, &mut context.openssl_bn_context)),
            None => {
                let mut ctx = try!(BigNumber::new_context());
                try!(BigNumRef::mod_inverse(&mut bn.openssl_bn, &self.openssl_bn, &n.openssl_bn, &mut ctx.openssl_bn_context));
            }
        }
        Ok(bn)
    }

    pub fn mod_div(&self, b: &BigNumber, p: &BigNumber) -> Result<BigNumber, CryptoError> {
        //(a*  (1/b mod p) mod p)

        let mut context = try!(BigNumber::new_context());

        let res = try!(
            b
                .inverse(p, Some(&mut context))?
                .mul(&self, Some(&mut context))?
                .modulus(&p, Some(&mut context))
        );
        Ok(res)
    }

    pub fn clone(&self) -> Result<BigNumber, CryptoError> {
        let bytes = try!(self.to_bytes());
        let bn = try!(BigNumber::from_bytes(bytes.as_slice()));
        Ok(bn)
    }
}

impl Ord for BigNumber {
    fn cmp(&self, other: &BigNumber) -> Ordering {
        self.openssl_bn.ucmp(&other.openssl_bn)
    }
}

impl Eq for BigNumber {}

impl PartialOrd for BigNumber {
    fn partial_cmp(&self, other: &BigNumber) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for BigNumber {
    fn eq(&self, other: &BigNumber) -> bool {
        self.openssl_bn == other.openssl_bn
    }
}

impl From<ErrorStack> for CryptoError {
    fn from(err: ErrorStack) -> CryptoError {
        CryptoError::BackendError(err.description().to_string())
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn generate_prime_in_range_works() {
        ::env_logger::init().unwrap();

        let bn = BigNumber::new().unwrap();
        let start = bn.rand(250).unwrap();
        let end = bn.rand(300).unwrap();
        let random_prime = bn.generate_prime_in_range(&start, &end).unwrap();
        assert!(start < random_prime);
        assert!(end > random_prime);
    }
}<|endoftext|>


<commit_before>use std;
use std::collections::HashMap;

static REF_FREQS: [(u8, f32); 28] = [
    (b' ', 12.17),
    (b'.', 6.57),
    (b'a', 6.09),
    (b'b', 1.05),
    (b'c', 2.84),
    (b'd', 2.92),
    (b'e', 11.36),
    (b'f', 1.79),
    (b'g', 1.38),
    (b'h', 3.41),
    (b'i', 5.44),
    (b'j', 0.24),
    (b'k', 0.41),
    (b'l', 2.92),
    (b'm', 2.76),
    (b'n', 5.44),
    (b'o', 6.00),
    (b'p', 1.95),
    (b'q', 0.24),
    (b'r', 4.95),
    (b's', 5.68),
    (b't', 8.03),
    (b'u', 2.43),
    (b'v', 0.97),
    (b'w', 1.38),
    (b'x', 0.24),
    (b'y', 1.30),
    (b'z', 0.03),
];

pub fn compute_score(v: &[u8]) -> u32 {
    if !v.is_ascii() {
        return std::u32::MAX;
    }

    if v.iter().any(|&c| is_control(c) && c != b'\n') {
        return std::u32::MAX;
    }

    let freqs = get_character_frequencies(v);

    let length = v.len() as f32;
    REF_FREQS.iter().fold(0f32, |a, &(c, score)| {
        let ref_count = score / 100f32 * length;
        let &obs_count = freqs.get(&c).unwrap_or(&0f32);
        a + (ref_count - obs_count).powi(2)
    }) as u32
}

fn is_control(u: u8) -> bool {
    u < 0x20 || u == 0x7F
}

fn is_alphabetic(u: u8) -> bool {
    (u >= 0x41 && u <= 0x5A) || (u >= 0x61 && u <= 0x7A)
}

fn get_character_frequencies(v: &[u8]) -> HashMap<u8, f32> {
    let mut freqs: HashMap<u8, f32> = HashMap::new();
    for &c in v.iter() {
        if is_control(c) {
            continue;
        }
        let key = if is_alphabetic(c) {
            c.to_ascii_lowercase()
        } else if c == b' ' || c == b'\t' {
            b' '
        } else {
            b'.'
        };

        let freq = freqs.entry(key).or_insert(0f32);
        *freq += 1f32;
    }
    freqs
}

pub fn ceil_div(n: usize, k: usize) -> (usize, usize) {
    let q = (n + k - 1) / k;
    let r = q * k - n;
    (q, r)
}
<commit_msg>Cleanup<commit_after>pub fn ceil_div(n: usize, k: usize) -> (usize, usize) {
    let q = (n + k - 1) / k;
    let r = q * k - n;
    (q, r)
}
<|endoftext|>


<commit_before>use super::backend::RendererServer;

/// Start the turtle window in advance
///
/// If you do not create a turtle immediately at the beginning of `main()` with [`Turtle::new()`],
/// you must call this function at the start of `main()` to avoid any problems.
///
/// Since the majority of code created using this crate does little or no work before calling
/// [`Turtle::new()`], this usually isn't a problem. Programs that parse command line arguments,
/// read input, or check environment variables may **fail** to start if this function is not called
/// right at the beginning of the program. Programs that perform any expensive computations may
/// experience delayed start up problems unless they call this function first.
///
/// The [`Turtle::new()`] method will call this function for you so that you don't need to worry
/// about this unless you are doing something before that.
///
/// # Example
/// ```rust,no_run
/// # #![allow(unused_variables, unused_mut)]
/// use turtle::Turtle;
///
/// fn main() {
///     // Initializes the turtle renderer first so that there is less delay when a Turtle
///     // is created and so that there are no conflicts with command line arguments or
///     // environment variables.
///     // Not required if Turtle::new() is already at the top of main.
///     turtle::start();
///
///     // Do all kinds of expensive work here...
///     // Feel free to check environment variables, command line arguments, etc.
///
///     // Create the turtle when you are ready
///     // Turtle::new() will also call start(), but calling it twice doesn't matter
///     let mut turtle = Turtle::new();
///     // Do things with the turtle...
/// }
/// ```
///
/// [`Turtle::new()`]: struct.Turtle.html#method.new
pub fn start() {
    // This check is performed on all platforms to help avoid compatibility hazards that may
    // accidentally make it harder to run a turtle program on a different platform. The check is
    // not foolproof and there is no way to verify that start() is called at the beginning of
    // main() in all cases. This is just to help in the cases where we can detect something.
    #[cfg(not(any(feature = "test", test)))]
    assert_main_thread();

    RendererServer::start();
}

#[cfg(not(any(feature = "test", test)))]
fn assert_main_thread() {
    // This check isn't foolproof. Someone can always create a thread named "main".
    if std::thread::current().name().unwrap_or("") != "main" {
        // In order to maintain compatibility with MacOS, we need to make sure that windows are
        // only created on the main thread. We do this check on all platforms so that no one
        // can accidentally make a change that creates the window off of the main thread.
        //
        // It's easy for a user to accidentally cause this panic if they call `Turtle::new()` in a
        // new thread. This message is meant to point them to the solution: `turtle::start()`
        panic!("Windows can only be created on the main thread. Make sure you have called \
                `turtle::start()` at the beginning of your program's main() function. \
                See: <https://docs.rs/turtle/*/turtle/fn.start.html>");
    }
}
<commit_msg>Ensuring that main thread check only executes once in start()<commit_after>#[cfg(not(any(feature = "test", test)))]
use std::sync::atomic::{AtomicBool, Ordering};

use super::backend::RendererServer;

/// `start()` must be called once from the main thread, but it can be called after that any number
/// of times. This flag helps ensure that the main thread check only executes the first time.
#[cfg(not(any(feature = "test", test)))]
static START_RAN_ONCE: AtomicBool = AtomicBool::new(false);

/// Start the turtle window in advance
///
/// If you do not create a turtle immediately at the beginning of `main()` with [`Turtle::new()`],
/// you must call this function at the start of `main()` to avoid any problems.
///
/// Since the majority of code created using this crate does little or no work before calling
/// [`Turtle::new()`], this usually isn't a problem. Programs that parse command line arguments,
/// read input, or check environment variables may **fail** to start if this function is not called
/// right at the beginning of the program. Programs that perform any expensive computations may
/// experience delayed start up problems unless they call this function first.
///
/// The [`Turtle::new()`] method will call this function for you so that you don't need to worry
/// about this unless you are doing something before that.
///
/// # Example
/// ```rust,no_run
/// # #![allow(unused_variables, unused_mut)]
/// use turtle::Turtle;
///
/// fn main() {
///     // Initializes the turtle renderer first so that there is less delay when a Turtle
///     // is created and so that there are no conflicts with command line arguments or
///     // environment variables.
///     // Not required if Turtle::new() is already at the top of main.
///     turtle::start();
///
///     // Do all kinds of expensive work here...
///     // Feel free to check environment variables, command line arguments, etc.
///
///     // Create the turtle when you are ready
///     // Turtle::new() will also call start(), but calling it twice doesn't matter
///     let mut turtle = Turtle::new();
///     // Do things with the turtle...
/// }
/// ```
///
/// [`Turtle::new()`]: struct.Turtle.html#method.new
pub fn start() {
    // This check is performed on all platforms to help avoid compatibility hazards that may
    // accidentally make it harder to run a turtle program on a different platform. The check is
    // not foolproof and there is no way to verify that start() is called at the beginning of
    // main() in all cases. This is just to help in the cases where we can detect something.
    #[cfg(not(any(feature = "test", test)))]
    if !START_RAN_ONCE.swap(true, Ordering::SeqCst) {
        assert_main_thread();
    }

    RendererServer::start();
}

#[cfg(not(any(feature = "test", test)))]
fn assert_main_thread() {
    // This check isn't foolproof. Someone can always create a thread named "main".
    if std::thread::current().name().unwrap_or("") != "main" {
        // In order to maintain compatibility with MacOS, we need to make sure that windows are
        // only created on the main thread. We do this check on all platforms so that no one
        // can accidentally make a change that creates the window off of the main thread.
        //
        // It's easy for a user to accidentally cause this panic if they call `Turtle::new()` in a
        // new thread. This message is meant to point them to the solution: `turtle::start()`
        panic!("Windows can only be created on the main thread. Make sure you have called \
                `turtle::start()` at the beginning of your program's main() function. \
                See: <https://docs.rs/turtle/*/turtle/fn.start.html>");
    }
}
<|endoftext|>


<commit_before>// compile-flags: -Z unstable-options --scrape-examples-output-path t.calls --scrape-examples-target-crate foobar
// check-pass
#![no_std]
use core as _;
<commit_msg>Change output path to {{build-base}}<commit_after>// compile-flags: -Z unstable-options --scrape-examples-output-path {{build-base}}/t.calls --scrape-examples-target-crate foobar
// check-pass
#![no_std]
use core as _;
<|endoftext|>