<commit_before>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//! Asynchronous GUI library based on GTK+ and futures/tokio.
//!
//! This library provides a `Widget` trait that you can use to create asynchronous GUI components.
//! This is the trait you will need to implement for your application.
//! It helps you to implement MVC (Model, View, Controller) in an elegant way.
//!
//! ## Installation
//! Add this to your `Cargo.toml`:
//! ```toml
//! [dependencies]
//! gtk = "^0.1.2"
//! relm = "^0.5.0"
//! relm-derive = "^0.1.2"
//! ```
//!
//! More info can be found in the [readme](https://github.com/antoyo/relm#relm).

#![cfg_attr(feature = "use_impl_trait", feature(conservative_impl_trait))]
#![warn(missing_docs, trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

/*
 * TODO: add a PrivateMsg type and an update_private() method to the Update trait to allow internal
 * messages to be send without requiring Clone.
 * TODO: add construct-only properties for relm widget (to replace initial parameters) to allow
 * setting them by name (or with default value).
 * TODO: find a way to do two-step initialization (to avoid using unitialized in model()).
 * TODO: consider using GBinding instead of manually adding calls to set_property().
 * TODO: remove the closure transformer code.
 *
 * TODO: show a warning when components are destroyed after the end of call to Widget::view().
 * TODO: warn in the attribute when an event cycle is found.
 * TODO: add a Deref<Widget> for Component?
 * TODO: look at how Elm works with the <canvas> element.
 * TODO: the widget names should start with __relm_field_.
 *
 * TODO: reset widget name counters when creating new widget?
 *
 * TODO: refactor the code.
 *
 * TODO: chat client/server example.
 *
 * TODO: err if trying to use the SimpleMsg custom derive on stable.
 *
 * TODO: add default type of () for Model in Widget when it is stable.
 * TODO: optionnaly multi-threaded.
 * TODO: convert GTK+ callback to Stream (does not seem worth it, nor convenient since it will
 * still need to use USFC for the callback method).
 *
 * These probably won't be needed anymore when switching to futures-glib (single-threaded model).
 * TODO: use weak pointers to avoid leaking.
 * TODO: should have a free function to delete the stream in connect_recv.
 * TODO: try tk-easyloop in another branch.
 */

extern crate futures;
extern crate futures_glib;
extern crate glib;
extern crate glib_sys;
extern crate gobject_sys;
extern crate gtk;
extern crate gtk_sys;
extern crate libc;
extern crate relm_core;
extern crate relm_state;

mod callback;
mod container;
mod macros;
mod widget;

use futures_glib::MainContext;
#[doc(hidden)]
pub use glib::Cast;
#[doc(hidden)]
pub use glib::object::Downcast;
#[doc(hidden)]
pub use glib::translate::{FromGlibPtrNone, ToGlib, ToGlibPtr};
use glib_sys::GType;
#[doc(hidden)]
pub use gobject_sys::{GParameter, g_object_newv};
use gobject_sys::{GObject, GValue};
use libc::{c_char, c_uint};
#[doc(hidden)]
pub use relm_core::EventStream;
pub use relm_state::{Component, DisplayVariant, IntoOption, IntoPair, Relm, Update};
use relm_state::init_component;

pub use callback::Resolver;
pub use container::{Container, ContainerWidget, RelmContainer};
pub use widget::Widget;

extern "C" {
    pub fn g_object_new_with_properties(object_type: GType, n_properties: c_uint, names: *mut *const c_char,
                                        values: *mut *const GValue) -> *mut GObject;
}

/// Dummy macro to be used with `#[derive(Widget)]`.
///
/// An example can be found [here](https://github.com/antoyo/relm/blob/master/examples/buttons-derive/src/main.rs#L52).
#[macro_export]
macro_rules! impl_widget {
    ($($tt:tt)*) => {
        ()
    };
}

/// Macro to be used as a stable alternative to the #[widget] attribute.
#[macro_export]
macro_rules! relm_widget {
    ($($tts:tt)*) => {
        mod __relm_gen_private {
            use super::*;

            #[derive(Widget)]
            struct __RelmPrivateWidget {
                widget: impl_widget! {
                    $($tts)*
                }
            }
        }

        use_impl_self_type!($($tts)*);
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! use_impl_self_type {
    (impl Widget for $self_type:ident { $($tts:tt)* }) => {
        pub use self::__relm_gen_private::$self_type;
    };
}

fn create_widget_test<WIDGET>(cx: &MainContext, model_param: WIDGET::ModelParam) -> Component<WIDGET>
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    let (component, relm) = create_widget(cx, model_param);
    init_component::<WIDGET>(&component, cx, &relm);
    component
}

/// Create a new relm widget without adding it to an existing widget.
/// This is useful when a relm widget is at the root of another relm widget.
pub fn create_component<CHILDWIDGET, WIDGET>(relm: &Relm<WIDGET>, model_param: CHILDWIDGET::ModelParam)
        -> Component<CHILDWIDGET>
    where CHILDWIDGET: Widget + 'static,
          CHILDWIDGET::Msg: DisplayVariant + 'static,
          WIDGET: Widget,
{
    let (component, child_relm) = create_widget::<CHILDWIDGET>(relm.context(), model_param);
    init_component::<CHILDWIDGET>(&component, relm.context(), &child_relm);
    component
}

fn create_widget<WIDGET>(cx: &MainContext, model_param: WIDGET::ModelParam) -> (Component<WIDGET>, Relm<WIDGET>)
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    let stream = EventStream::new();

    let relm = Relm::new(cx.clone(), stream.clone());
    let model = WIDGET::model(&relm, model_param);
    let widget = WIDGET::view(&relm, model);
    widget.borrow_mut().init_view();

    (Component::new(stream, widget), relm)
}

// TODO: remove this workaround.
fn init_gtk() {
    let mut argc = 0;
    unsafe {
        gtk_sys::gtk_init(&mut argc, std::ptr::null_mut());
        gtk::set_initialized();
    }
}

/// Initialize a widget for a test.
///
/// It is to be used this way:
/// ```
/// # extern crate gtk;
/// # #[macro_use]
/// # extern crate relm;
/// # #[macro_use]
/// # extern crate relm_derive;
/// #
/// # use gtk::{Window, WindowType};
/// # use relm::{Relm, Widget};
/// #
/// # struct Win {
/// #     window: Window,
/// # }
/// #
/// # impl Widget for Win {
/// #     type Model = ();
/// #     type ModelParam = ();
/// #     type Msg = Msg;
/// #     type Root = Window;
/// #
/// #     fn model(_: ()) -> () {
/// #         ()
/// #     }
/// #
/// #     fn root(&self) -> &Self::Root {
/// #         &self.window
/// #     }
/// #
/// #     fn update(&mut self, event: Msg, model: &mut Self::Model) {
/// #     }
/// #
/// #     fn view(relm: Relm<Msg>, _model: &Self::Model) -> Self {
/// #         let window = Window::new(WindowType::Toplevel);
/// #
/// #         Win {
/// #             window: window,
/// #         }
/// #     }
/// # }
/// #
/// # #[derive(Msg)]
/// # enum Msg {}
/// # fn main() {
/// let component = relm::init_test::<Win>().unwrap();
/// let widgets = component.widget();
/// # }
/// ```
pub fn init_test<WIDGET>(model_param: WIDGET::ModelParam) -> Result<Component<WIDGET>, ()>
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static
{
    futures_glib::init();
    init_gtk();

    let cx = MainContext::default(|cx| cx.clone());
    let component = create_widget_test::<WIDGET>(&cx);
    Ok(component)
}

fn init<WIDGET>(model_param: WIDGET::ModelParam) -> Result<Component<WIDGET>, ()>
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static
{
    futures_glib::init();
    gtk::init()?;

    let cx = MainContext::default(|cx| cx.clone());
    let (component, relm) = create_widget::<WIDGET>(&cx, model_param);
    init_component::<WIDGET>(&component, &cx, &relm);
    Ok(component)
}

/// Create the specified relm `Widget` and run the main event loops.
/// ```
/// # extern crate gtk;
/// # #[macro_use]
/// # extern crate relm;
/// # #[macro_use]
/// # extern crate relm_derive;
/// #
/// # use gtk::{Window, WindowType};
/// # use relm::{Relm, Widget};
/// #
/// # struct Win {
/// #     window: Window,
/// # }
/// #
/// # impl Widget for Win {
/// #     type Model = ();
/// #     type ModelParam = ();
/// #     type Msg = Msg;
/// #     type Root = Window;
/// #
/// #     fn model(_: ()) -> () {
/// #         ()
/// #     }
/// #
/// #     fn root(&self) -> &Self::Root {
/// #         &self.window
/// #     }
/// #
/// #     fn update(&mut self, event: Msg, model: &mut Self::Model) {
/// #     }
/// #
/// #     fn view(relm: Relm<Msg>, _model: &Self::Model) -> Self {
/// #         let window = Window::new(WindowType::Toplevel);
/// #
/// #         Win {
/// #             window: window,
/// #         }
/// #     }
/// # }
/// # #[derive(Msg)]
/// # enum Msg {}
/// # fn main() {
/// # }
/// #
/// # fn run() {
/// /// `Win` is a relm `Widget`.
/// Win::run(()).unwrap();
/// # }
/// ```
pub fn run<WIDGET>(model_param: WIDGET::ModelParam) -> Result<(), ()>
    where WIDGET: Widget + 'static,
          WIDGET::ModelParam: Default,
{
    let _component = init::<WIDGET>(model_param)?;
    gtk::main();
    Ok(())
}
<commit_msg>Add missing reexport of relm_state::execute<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//! Asynchronous GUI library based on GTK+ and futures/tokio.
//!
//! This library provides a `Widget` trait that you can use to create asynchronous GUI components.
//! This is the trait you will need to implement for your application.
//! It helps you to implement MVC (Model, View, Controller) in an elegant way.
//!
//! ## Installation
//! Add this to your `Cargo.toml`:
//! ```toml
//! [dependencies]
//! gtk = "^0.1.2"
//! relm = "^0.5.0"
//! relm-derive = "^0.1.2"
//! ```
//!
//! More info can be found in the [readme](https://github.com/antoyo/relm#relm).

#![cfg_attr(feature = "use_impl_trait", feature(conservative_impl_trait))]
#![warn(missing_docs, trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

/*
 * TODO: add a PrivateMsg type and an update_private() method to the Update trait to allow internal
 * messages to be send without requiring Clone.
 * TODO: add construct-only properties for relm widget (to replace initial parameters) to allow
 * setting them by name (or with default value).
 * TODO: find a way to do two-step initialization (to avoid using unitialized in model()).
 * TODO: consider using GBinding instead of manually adding calls to set_property().
 * TODO: remove the closure transformer code.
 *
 * TODO: show a warning when components are destroyed after the end of call to Widget::view().
 * TODO: warn in the attribute when an event cycle is found.
 * TODO: add a Deref<Widget> for Component?
 * TODO: look at how Elm works with the <canvas> element.
 * TODO: the widget names should start with __relm_field_.
 *
 * TODO: reset widget name counters when creating new widget?
 *
 * TODO: refactor the code.
 *
 * TODO: chat client/server example.
 *
 * TODO: err if trying to use the SimpleMsg custom derive on stable.
 *
 * TODO: add default type of () for Model in Widget when it is stable.
 * TODO: optionnaly multi-threaded.
 * TODO: convert GTK+ callback to Stream (does not seem worth it, nor convenient since it will
 * still need to use USFC for the callback method).
 *
 * These probably won't be needed anymore when switching to futures-glib (single-threaded model).
 * TODO: use weak pointers to avoid leaking.
 * TODO: should have a free function to delete the stream in connect_recv.
 * TODO: try tk-easyloop in another branch.
 */

extern crate futures;
extern crate futures_glib;
extern crate glib;
extern crate glib_sys;
extern crate gobject_sys;
extern crate gtk;
extern crate gtk_sys;
extern crate libc;
extern crate relm_core;
extern crate relm_state;

mod callback;
mod container;
mod macros;
mod widget;

use futures_glib::MainContext;
#[doc(hidden)]
pub use glib::Cast;
#[doc(hidden)]
pub use glib::object::Downcast;
#[doc(hidden)]
pub use glib::translate::{FromGlibPtrNone, ToGlib, ToGlibPtr};
use glib_sys::GType;
#[doc(hidden)]
pub use gobject_sys::{GParameter, g_object_newv};
use gobject_sys::{GObject, GValue};
use libc::{c_char, c_uint};
#[doc(hidden)]
pub use relm_core::EventStream;
pub use relm_state::{Component, DisplayVariant, IntoOption, IntoPair, Relm, Update, execute};
use relm_state::init_component;

pub use callback::Resolver;
pub use container::{Container, ContainerWidget, RelmContainer};
pub use widget::Widget;

extern "C" {
    pub fn g_object_new_with_properties(object_type: GType, n_properties: c_uint, names: *mut *const c_char,
                                        values: *mut *const GValue) -> *mut GObject;
}

/// Dummy macro to be used with `#[derive(Widget)]`.
///
/// An example can be found [here](https://github.com/antoyo/relm/blob/master/examples/buttons-derive/src/main.rs#L52).
#[macro_export]
macro_rules! impl_widget {
    ($($tt:tt)*) => {
        ()
    };
}

/// Macro to be used as a stable alternative to the #[widget] attribute.
#[macro_export]
macro_rules! relm_widget {
    ($($tts:tt)*) => {
        mod __relm_gen_private {
            use super::*;

            #[derive(Widget)]
            struct __RelmPrivateWidget {
                widget: impl_widget! {
                    $($tts)*
                }
            }
        }

        use_impl_self_type!($($tts)*);
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! use_impl_self_type {
    (impl Widget for $self_type:ident { $($tts:tt)* }) => {
        pub use self::__relm_gen_private::$self_type;
    };
}

fn create_widget_test<WIDGET>(cx: &MainContext, model_param: WIDGET::ModelParam) -> Component<WIDGET>
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    let (component, relm) = create_widget(cx, model_param);
    init_component::<WIDGET>(&component, cx, &relm);
    component
}

/// Create a new relm widget without adding it to an existing widget.
/// This is useful when a relm widget is at the root of another relm widget.
pub fn create_component<CHILDWIDGET, WIDGET>(relm: &Relm<WIDGET>, model_param: CHILDWIDGET::ModelParam)
        -> Component<CHILDWIDGET>
    where CHILDWIDGET: Widget + 'static,
          CHILDWIDGET::Msg: DisplayVariant + 'static,
          WIDGET: Widget,
{
    let (component, child_relm) = create_widget::<CHILDWIDGET>(relm.context(), model_param);
    init_component::<CHILDWIDGET>(&component, relm.context(), &child_relm);
    component
}

fn create_widget<WIDGET>(cx: &MainContext, model_param: WIDGET::ModelParam) -> (Component<WIDGET>, Relm<WIDGET>)
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    let stream = EventStream::new();

    let relm = Relm::new(cx.clone(), stream.clone());
    let model = WIDGET::model(&relm, model_param);
    let widget = WIDGET::view(&relm, model);
    widget.borrow_mut().init_view();

    (Component::new(stream, widget), relm)
}

// TODO: remove this workaround.
fn init_gtk() {
    let mut argc = 0;
    unsafe {
        gtk_sys::gtk_init(&mut argc, std::ptr::null_mut());
        gtk::set_initialized();
    }
}

/// Initialize a widget for a test.
///
/// It is to be used this way:
/// ```
/// # extern crate gtk;
/// # #[macro_use]
/// # extern crate relm;
/// # #[macro_use]
/// # extern crate relm_derive;
/// #
/// # use gtk::{Window, WindowType};
/// # use relm::{Relm, Widget};
/// #
/// # struct Win {
/// #     window: Window,
/// # }
/// #
/// # impl Widget for Win {
/// #     type Model = ();
/// #     type ModelParam = ();
/// #     type Msg = Msg;
/// #     type Root = Window;
/// #
/// #     fn model(_: ()) -> () {
/// #         ()
/// #     }
/// #
/// #     fn root(&self) -> &Self::Root {
/// #         &self.window
/// #     }
/// #
/// #     fn update(&mut self, event: Msg, model: &mut Self::Model) {
/// #     }
/// #
/// #     fn view(relm: Relm<Msg>, _model: &Self::Model) -> Self {
/// #         let window = Window::new(WindowType::Toplevel);
/// #
/// #         Win {
/// #             window: window,
/// #         }
/// #     }
/// # }
/// #
/// # #[derive(Msg)]
/// # enum Msg {}
/// # fn main() {
/// let component = relm::init_test::<Win>().unwrap();
/// let widgets = component.widget();
/// # }
/// ```
pub fn init_test<WIDGET>(model_param: WIDGET::ModelParam) -> Result<Component<WIDGET>, ()>
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static
{
    futures_glib::init();
    init_gtk();

    let cx = MainContext::default(|cx| cx.clone());
    let component = create_widget_test::<WIDGET>(&cx);
    Ok(component)
}

fn init<WIDGET>(model_param: WIDGET::ModelParam) -> Result<Component<WIDGET>, ()>
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static
{
    futures_glib::init();
    gtk::init()?;

    let cx = MainContext::default(|cx| cx.clone());
    let (component, relm) = create_widget::<WIDGET>(&cx, model_param);
    init_component::<WIDGET>(&component, &cx, &relm);
    Ok(component)
}

/// Create the specified relm `Widget` and run the main event loops.
/// ```
/// # extern crate gtk;
/// # #[macro_use]
/// # extern crate relm;
/// # #[macro_use]
/// # extern crate relm_derive;
/// #
/// # use gtk::{Window, WindowType};
/// # use relm::{Relm, Widget};
/// #
/// # struct Win {
/// #     window: Window,
/// # }
/// #
/// # impl Widget for Win {
/// #     type Model = ();
/// #     type ModelParam = ();
/// #     type Msg = Msg;
/// #     type Root = Window;
/// #
/// #     fn model(_: ()) -> () {
/// #         ()
/// #     }
/// #
/// #     fn root(&self) -> &Self::Root {
/// #         &self.window
/// #     }
/// #
/// #     fn update(&mut self, event: Msg, model: &mut Self::Model) {
/// #     }
/// #
/// #     fn view(relm: Relm<Msg>, _model: &Self::Model) -> Self {
/// #         let window = Window::new(WindowType::Toplevel);
/// #
/// #         Win {
/// #             window: window,
/// #         }
/// #     }
/// # }
/// # #[derive(Msg)]
/// # enum Msg {}
/// # fn main() {
/// # }
/// #
/// # fn run() {
/// /// `Win` is a relm `Widget`.
/// Win::run(()).unwrap();
/// # }
/// ```
pub fn run<WIDGET>(model_param: WIDGET::ModelParam) -> Result<(), ()>
    where WIDGET: Widget + 'static,
          WIDGET::ModelParam: Default,
{
    let _component = init::<WIDGET>(model_param)?;
    gtk::main();
    Ok(())
}
<|endoftext|>


<commit_before>extern crate emailaddress;
#[macro_use]
extern crate log;
extern crate hyper;
extern crate iron;
extern crate lettre;
extern crate mustache;
extern crate redis;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate url;
extern crate urlencoded;

use emailaddress::EmailAddress;
use iron::headers::{ContentType, Location};
use iron::middleware::Handler;
use iron::modifiers;
use iron::method::Method;
use iron::prelude::*;
use iron::status;
use iron::typemap;
use iron::Url;
use serde_json::builder::{ArrayBuilder, ObjectBuilder};
use serde_json::value::Value;
use std::env;
use std::fs::File;
use std::io::{BufReader, Read};
use std::sync::Arc;
use std::error::Error;
use time::now_utc;
use urlencoded::{UrlEncodedBody, UrlEncodedQuery};

pub mod error;
pub mod config;
pub use config::{Config, ConfigBuilder};
pub mod crypto;
pub mod email;
pub mod oidc;
pub mod store;
pub mod store_cache;

use error::{BrokerResult, BrokerError};

/// Iron extension key we use to store the `redirect_uri`.
/// Once set, the error handler will return errors to the RP.
struct RedirectUri;
impl typemap::Key for RedirectUri { type Value = Url; }

/// Macro that creates Handler implementations that log the request,
/// and keep a reference to the Config.
macro_rules! broker_handler {
    ( $name:ident , | $app:ident, $req:ident | $body:block ) => {
        pub struct $name {
            pub app: Arc<Config>,
        }
        impl $name {
            pub fn new(app: &Arc<Config>) -> Self {
                $name { app: app.clone() }
            }
            fn handle_body($app: &Config, $req: &mut Request)
                -> BrokerResult<Response> $body
        }
        impl Handler for $name {
            fn handle(&self, req: &mut Request) -> IronResult<Response> {
                info!("{} {}", req.method, req.url);
                Self::handle_body(&self.app, req)
                    .or_else(|e| handle_error(&self.app, req, e))
            }
        }
    }
}

/// Macro used to extract a parameter from a QueryMap.
///
/// Will return from the caller with a `BrokerError` if
/// the parameter is missing and has no default.
///
/// ```
/// let foo = try_get_param!(params, "foo");
/// let foo = try_get_param!(params, "foo", "default");
/// ```
macro_rules! try_get_param {
    ( $input:expr , $param:tt ) => {
        try!($input.get($param).map(|list| list[0].as_str()).ok_or_else(|| {
            BrokerError::Input(concat!("missing request parameter ", $param).to_string())
        }))
    };
    ( $input:expr , $param:tt, $default:tt ) => {
        $input.get($param).map(|list| list[0].as_str()).unwrap_or($default)
    };
}

/// Helper function for returning a result to the Relying Party.
///
/// Takes an array of `(name, value)` parameter pairs to send to the relier and
/// embeds them in a form in `tmpl/forward.html`, from where it's POSTed to the
/// RP's `redirect_uri` as soon as the page has loaded.
///
/// The return value is a tuple of response modifiers.
fn return_to_relier(app: &Config, redirect_uri: &str, params: &[(&str, &str)])
    -> (hyper::status::StatusCode, modifiers::Header<ContentType>, String) {
    let data = mustache::MapBuilder::new()
        .insert_str("redirect_uri", redirect_uri)
        .insert_vec("params", |mut builder| {
            for &param in params {
                builder = builder.push_map(|builder| {
                    let (name, value) = param;
                    builder.insert_str("name", name).insert_str("value", value)
                });
            }
            builder
        })
        .build();
    (status::Ok,
     modifiers::Header(ContentType::html()),
     app.templates.forward.render_data(&data))
}

/// Handle an `BrokerError` and create an `IronResult`.
///
/// The `broker_handler!` macro calls this on error. We don't use a `From`
/// implementation, because this way we get app and request context, and we
/// don't necessarily have to pass the error on to Iron.
///
/// When we handle an error, we want to:
///
///  - Log internal errors and errors related to communcation with providers.
///  - Not log input errors, such as missing parameters.
///
///  - Hide the details of internal errors from the user.
///  - Show a description for input and provider errors.
///
///  - Return the error to the relier via redirect, as per the OAuth2 spec.
///  - Always show something to the user, even if we cannot redirect.
///
/// The large match-statement below handles all these scenario's properly,
/// and sets proper response codes for each category.
fn handle_error(app: &Config, req: &mut Request, err: BrokerError) -> IronResult<Response> {
    let redirect_uri = req.extensions.remove::<RedirectUri>().map(|url| url.to_string());
    match (err, redirect_uri) {
        (err @ BrokerError::Input(_), Some(redirect_uri)) => {
            Ok(Response::with(return_to_relier(app, &redirect_uri, &[
                ("error", "invalid_request"),
                ("error_description", err.description()),
            ])))
        },
        (err @ BrokerError::Input(_), None) => {
            Ok(Response::with((status::BadRequest,
                               modifiers::Header(ContentType::html()),
                               app.templates.error.render(&[
                                   ("error", err.description()),
                               ]))))
        },
        (err @ BrokerError::Provider(_), Some(redirect_uri)) => {
            let description = err.description().to_string();
            Err(IronError::new(err, return_to_relier(app, &redirect_uri, &[
                ("error", "temporarily_unavailable"),
                ("error_description", &description),
            ])))
        },
        (err @ BrokerError::Provider(_), None) => {
            let description = err.description().to_string();
            Err(IronError::new(err, (status::ServiceUnavailable,
                                     modifiers::Header(ContentType::html()),
                                     app.templates.error.render(&[
                                         ("error", &description),
                                     ]))))
        },
        (err, Some(redirect_uri)) => {
            Err(IronError::new(err, return_to_relier(app, &redirect_uri, &[
                ("error", "server_error"),
            ])))
        },
        (err, None) => {
            Err(IronError::new(err, (status::InternalServerError,
                                     modifiers::Header(ContentType::html()),
                                     app.templates.error.render(&[
                                         ("error", "internal server error"),
                                     ]))))
        },
    }
}

/// Helper function for returning an Iron response with JSON data.
///
/// Serializes the argument value to JSON and returns a HTTP 200 response
/// code with the serialized JSON as the body.
fn json_response(obj: &Value) -> BrokerResult<Response> {
    let content = serde_json::to_string(&obj).unwrap();
    Ok(Response::with((status::Ok,
                       modifiers::Header(ContentType::json()),
                       content)))
}

/// Iron handler for the root path, returns human-friendly message.
///
/// This is not actually used in the protocol.
broker_handler!(WelcomeHandler, |_app, _req| {
    json_response(&ObjectBuilder::new()
        .insert("ladaemon", "Welcome")
        .insert("version", env!("CARGO_PKG_VERSION"))
        .build())
});

/// Iron handler for files in .well-known.
///
/// Mainly directed at Let's Encrypt verification. Returns text/plain always.
broker_handler!(WellKnownHandler, |_app, req| {
    let mut file_name = env::current_dir().unwrap();
    file_name.push(req.url.path().join("/"));
    let file_res = File::open(file_name);
    if file_res.is_err() {
        return Ok(Response::with((status::NotFound)));
    }
    let mut bytes = Vec::<u8>::new();
    let mut reader = BufReader::new(file_res.unwrap());
    let _ = reader.read_to_end(&mut bytes).unwrap();
    Ok(Response::with((status::Ok,
                       modifiers::Header(ContentType::plaintext()),
                       bytes)))
});

/// Iron handler to return the OpenID Discovery document.
///
/// Most of this is hard-coded for now, although the URLs are constructed by
/// using the base URL as configured in the `public_url` configuration value.
broker_handler!(OIDConfigHandler, |app, _req| {
    json_response(&ObjectBuilder::new()
        .insert("issuer", &app.public_url)
        .insert("authorization_endpoint",
                format!("{}/auth", app.public_url))
        .insert("jwks_uri", format!("{}/keys.json", app.public_url))
        .insert("scopes_supported", vec!["openid", "email"])
        .insert("claims_supported",
                vec!["aud", "email", "email_verified", "exp", "iat", "iss", "sub"])
        .insert("response_types_supported", vec!["id_token"])
        .insert("response_modes_supported", vec!["form_post"])
        .insert("grant_types_supported", vec!["implicit"])
        .insert("subject_types_supported", vec!["public"])
        .insert("id_token_signing_alg_values_supported", vec!["RS256"])
        .build())
});

/// Iron handler for the JSON Web Key Set document.
///
/// Respond with the JWK key set containing all of the configured keys.
///
/// Relying Parties will need to fetch this data to be able to verify identity
/// tokens issued by this daemon instance.
broker_handler!(KeysHandler, |app, _req| {
    let mut keys = ArrayBuilder::new();
    for key in &app.keys {
        keys = keys.push(key.public_jwk())
    }
    json_response(&ObjectBuilder::new()
                      .insert("keys", keys.build())
                      .build())
});

/// Iron handler for authentication requests from the RP.
///
/// Calls the `oidc::request()` function if the provided email address's
/// domain matches one of the configured famous providers. Otherwise, calls the
/// `email::request()` function to allow authentication through the email loop.
broker_handler!(AuthHandler, |app, req| {
    let params = try!(
        match req.method {
            Method::Get => {
                req.compute::<UrlEncodedQuery>()
                    .map_err(|_| BrokerError::Input("no query string in GET request".to_string()))
            },
            Method::Post => {
                req.compute::<UrlEncodedBody>()
                    .map_err(|_| BrokerError::Input("no query string in POST data".to_string()))
            },
            _ => {
                panic!("Unsupported method: {}", req.method)
            }
        }
    );

    // Per the OAuth2 spec, we may redirect to the RP once we have validated client_id and
    // redirect_uri. In our case, this means we make redirect_uri available to error handling.
    let client_id = try_get_param!(params, "client_id");
    let redirect_uri = try!(
        Url::parse(try_get_param!(params, "redirect_uri"))
            .map_err(|_| BrokerError::Input("redirect_uri is not a valid URL".to_string()))
    );
    req.extensions.insert::<RedirectUri>(redirect_uri.clone());

    if try_get_param!(params, "response_type") != "id_token" {
        return Err(BrokerError::Input("unsupported response_type, only id_token is supported".to_string()));
    }
    if try_get_param!(params, "response_mode", "fragment") != "form_post" {
        return Err(BrokerError::Input("unsupported response_mode, only form_post is supported".to_string()))
    }
    let email_addr = try!(
        EmailAddress::new(try_get_param!(params, "login_hint"))
            .map_err(|_| BrokerError::Input("login_hint is not a valid email address".to_string()))
    );
    let nonce = try_get_param!(params, "nonce");
    if app.providers.contains_key(&email_addr.domain) {

        // OIDC authentication. Redirect to the identity provider.
        let auth_url = try!(oidc::request(app, email_addr, client_id, nonce, &redirect_uri));
        Ok(Response::with((status::SeeOther, modifiers::Header(Location(auth_url.to_string())))))

    } else {

        // Email loop authentication. Render a message and form.
        let session_id = try!(email::request(app, email_addr, client_id, nonce, &redirect_uri));
        Ok(Response::with((status::Ok,
                           modifiers::Header(ContentType::html()),
                           app.templates.confirm_email.render(&[
                               ("client_id", &client_id),
                               ("session_id", &session_id),
                           ]))))

    }
});

/// Helper method to create a JWT for a given email address and origin.
///
/// Builds the JSON payload, then signs it using the last key provided in
/// the configuration object.
fn create_jwt(app: &Config, email: &str, origin: &str, nonce: &str) -> String {
    let now = now_utc().to_timespec().sec;
    let payload = &ObjectBuilder::new()
        .insert("aud", origin)
        .insert("email", email)
        .insert("email_verified", email)
        .insert("exp", now + app.token_ttl as i64)
        .insert("iat", now)
        .insert("iss", &app.public_url)
        .insert("sub", email)
        .insert("nonce", nonce)
        .build();
    app.keys.last().unwrap().sign_jws(payload)
}

/// Iron handler for one-time pad email loop confirmation.
///
/// Retrieves the session based session ID and the expected one-time pad.
/// Verify the code and return the resulting token or error to the RP.
broker_handler!(ConfirmHandler, |app, req| {
    let params = try!(
        req.compute::<UrlEncodedQuery>()
            .map_err(|_| BrokerError::Input("no query string in GET request".to_string()))
    );

    let stored = try!(app.store.get_session("email", &try_get_param!(params, "session")));
    req.extensions.insert::<RedirectUri>(Url::parse(&stored["redirect"]).unwrap());

    let code = try_get_param!(params, "code");
    let (jwt, redirect_uri) = try!(email::verify(app, &stored, code));
    Ok(Response::with(return_to_relier(app, &redirect_uri, &[("id_token", &jwt)])))
});

/// Iron handler for OAuth callbacks
///
/// After the user allows or denies the Authentication Request with the famous
/// identity provider, they will be redirected back to the callback handler.
/// Verify the callback data and return the resulting token or error.
broker_handler!(CallbackHandler, |app, req| {
    let params = try!(
        req.compute::<UrlEncodedQuery>()
            .map_err(|_| BrokerError::Input("no query string in GET request".to_string()))
    );

    let stored = try!(app.store.get_session("oidc", &try_get_param!(params, "state")));
    req.extensions.insert::<RedirectUri>(Url::parse(&stored["redirect"]).unwrap());

    let code = try_get_param!(params, "code");
    let (jwt, redirect_uri) = try!(oidc::verify(app, &stored, code));
    Ok(Response::with(return_to_relier(app, &redirect_uri, &[("id_token", &jwt)])))
});
<commit_msg>Fix clippy complaining about blocks in conditions<commit_after>extern crate emailaddress;
#[macro_use]
extern crate log;
extern crate hyper;
extern crate iron;
extern crate lettre;
extern crate mustache;
extern crate redis;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate url;
extern crate urlencoded;

use emailaddress::EmailAddress;
use iron::headers::{ContentType, Location};
use iron::middleware::Handler;
use iron::modifiers;
use iron::method::Method;
use iron::prelude::*;
use iron::status;
use iron::typemap;
use iron::Url;
use serde_json::builder::{ArrayBuilder, ObjectBuilder};
use serde_json::value::Value;
use std::env;
use std::fs::File;
use std::io::{BufReader, Read};
use std::sync::Arc;
use std::error::Error;
use time::now_utc;
use urlencoded::{UrlEncodedBody, UrlEncodedQuery};

pub mod error;
pub mod config;
pub use config::{Config, ConfigBuilder};
pub mod crypto;
pub mod email;
pub mod oidc;
pub mod store;
pub mod store_cache;

use error::{BrokerResult, BrokerError};

/// Iron extension key we use to store the `redirect_uri`.
/// Once set, the error handler will return errors to the RP.
struct RedirectUri;
impl typemap::Key for RedirectUri { type Value = Url; }

/// Macro that creates Handler implementations that log the request,
/// and keep a reference to the Config.
macro_rules! broker_handler {
    ( $name:ident , | $app:ident, $req:ident | $body:block ) => {
        pub struct $name {
            pub app: Arc<Config>,
        }
        impl $name {
            pub fn new(app: &Arc<Config>) -> Self {
                $name { app: app.clone() }
            }
            fn handle_body($app: &Config, $req: &mut Request)
                -> BrokerResult<Response> $body
        }
        impl Handler for $name {
            fn handle(&self, req: &mut Request) -> IronResult<Response> {
                info!("{} {}", req.method, req.url);
                Self::handle_body(&self.app, req)
                    .or_else(|e| handle_error(&self.app, req, e))
            }
        }
    }
}

/// Macro used to extract a parameter from a QueryMap.
///
/// Will return from the caller with a `BrokerError` if
/// the parameter is missing and has no default.
///
/// ```
/// let foo = try_get_param!(params, "foo");
/// let foo = try_get_param!(params, "foo", "default");
/// ```
macro_rules! try_get_param {
    ( $input:expr , $param:tt ) => {
        try!($input.get($param)
                   .and_then(|list| list.into_iter().nth(0))
                   .map(|s| s.as_str())
                   .ok_or_else(|| BrokerError::Input(concat!("missing request parameter ", $param).to_string()))
        )
    };
    ( $input:expr , $param:tt, $default:tt ) => {
        $input.get($param)
              .and_then(|list| list.into_iter().nth(0))
              .map(|s| s.as_str())
              .unwrap_or($default)
    };
}

/// Helper function for returning a result to the Relying Party.
///
/// Takes an array of `(name, value)` parameter pairs to send to the relier and
/// embeds them in a form in `tmpl/forward.html`, from where it's POSTed to the
/// RP's `redirect_uri` as soon as the page has loaded.
///
/// The return value is a tuple of response modifiers.
fn return_to_relier(app: &Config, redirect_uri: &str, params: &[(&str, &str)])
    -> (hyper::status::StatusCode, modifiers::Header<ContentType>, String) {
    let data = mustache::MapBuilder::new()
        .insert_str("redirect_uri", redirect_uri)
        .insert_vec("params", |mut builder| {
            for &param in params {
                builder = builder.push_map(|builder| {
                    let (name, value) = param;
                    builder.insert_str("name", name).insert_str("value", value)
                });
            }
            builder
        })
        .build();
    (status::Ok,
     modifiers::Header(ContentType::html()),
     app.templates.forward.render_data(&data))
}

/// Handle an `BrokerError` and create an `IronResult`.
///
/// The `broker_handler!` macro calls this on error. We don't use a `From`
/// implementation, because this way we get app and request context, and we
/// don't necessarily have to pass the error on to Iron.
///
/// When we handle an error, we want to:
///
///  - Log internal errors and errors related to communcation with providers.
///  - Not log input errors, such as missing parameters.
///
///  - Hide the details of internal errors from the user.
///  - Show a description for input and provider errors.
///
///  - Return the error to the relier via redirect, as per the OAuth2 spec.
///  - Always show something to the user, even if we cannot redirect.
///
/// The large match-statement below handles all these scenario's properly,
/// and sets proper response codes for each category.
fn handle_error(app: &Config, req: &mut Request, err: BrokerError) -> IronResult<Response> {
    let redirect_uri = req.extensions.remove::<RedirectUri>().map(|url| url.to_string());
    match (err, redirect_uri) {
        (err @ BrokerError::Input(_), Some(redirect_uri)) => {
            Ok(Response::with(return_to_relier(app, &redirect_uri, &[
                ("error", "invalid_request"),
                ("error_description", err.description()),
            ])))
        },
        (err @ BrokerError::Input(_), None) => {
            Ok(Response::with((status::BadRequest,
                               modifiers::Header(ContentType::html()),
                               app.templates.error.render(&[
                                   ("error", err.description()),
                               ]))))
        },
        (err @ BrokerError::Provider(_), Some(redirect_uri)) => {
            let description = err.description().to_string();
            Err(IronError::new(err, return_to_relier(app, &redirect_uri, &[
                ("error", "temporarily_unavailable"),
                ("error_description", &description),
            ])))
        },
        (err @ BrokerError::Provider(_), None) => {
            let description = err.description().to_string();
            Err(IronError::new(err, (status::ServiceUnavailable,
                                     modifiers::Header(ContentType::html()),
                                     app.templates.error.render(&[
                                         ("error", &description),
                                     ]))))
        },
        (err, Some(redirect_uri)) => {
            Err(IronError::new(err, return_to_relier(app, &redirect_uri, &[
                ("error", "server_error"),
            ])))
        },
        (err, None) => {
            Err(IronError::new(err, (status::InternalServerError,
                                     modifiers::Header(ContentType::html()),
                                     app.templates.error.render(&[
                                         ("error", "internal server error"),
                                     ]))))
        },
    }
}

/// Helper function for returning an Iron response with JSON data.
///
/// Serializes the argument value to JSON and returns a HTTP 200 response
/// code with the serialized JSON as the body.
fn json_response(obj: &Value) -> BrokerResult<Response> {
    let content = serde_json::to_string(&obj).unwrap();
    Ok(Response::with((status::Ok,
                       modifiers::Header(ContentType::json()),
                       content)))
}

/// Iron handler for the root path, returns human-friendly message.
///
/// This is not actually used in the protocol.
broker_handler!(WelcomeHandler, |_app, _req| {
    json_response(&ObjectBuilder::new()
        .insert("ladaemon", "Welcome")
        .insert("version", env!("CARGO_PKG_VERSION"))
        .build())
});

/// Iron handler for files in .well-known.
///
/// Mainly directed at Let's Encrypt verification. Returns text/plain always.
broker_handler!(WellKnownHandler, |_app, req| {
    let mut file_name = env::current_dir().unwrap();
    file_name.push(req.url.path().join("/"));
    let file_res = File::open(file_name);
    if file_res.is_err() {
        return Ok(Response::with((status::NotFound)));
    }
    let mut bytes = Vec::<u8>::new();
    let mut reader = BufReader::new(file_res.unwrap());
    let _ = reader.read_to_end(&mut bytes).unwrap();
    Ok(Response::with((status::Ok,
                       modifiers::Header(ContentType::plaintext()),
                       bytes)))
});

/// Iron handler to return the OpenID Discovery document.
///
/// Most of this is hard-coded for now, although the URLs are constructed by
/// using the base URL as configured in the `public_url` configuration value.
broker_handler!(OIDConfigHandler, |app, _req| {
    json_response(&ObjectBuilder::new()
        .insert("issuer", &app.public_url)
        .insert("authorization_endpoint",
                format!("{}/auth", app.public_url))
        .insert("jwks_uri", format!("{}/keys.json", app.public_url))
        .insert("scopes_supported", vec!["openid", "email"])
        .insert("claims_supported",
                vec!["aud", "email", "email_verified", "exp", "iat", "iss", "sub"])
        .insert("response_types_supported", vec!["id_token"])
        .insert("response_modes_supported", vec!["form_post"])
        .insert("grant_types_supported", vec!["implicit"])
        .insert("subject_types_supported", vec!["public"])
        .insert("id_token_signing_alg_values_supported", vec!["RS256"])
        .build())
});

/// Iron handler for the JSON Web Key Set document.
///
/// Respond with the JWK key set containing all of the configured keys.
///
/// Relying Parties will need to fetch this data to be able to verify identity
/// tokens issued by this daemon instance.
broker_handler!(KeysHandler, |app, _req| {
    let mut keys = ArrayBuilder::new();
    for key in &app.keys {
        keys = keys.push(key.public_jwk())
    }
    json_response(&ObjectBuilder::new()
                      .insert("keys", keys.build())
                      .build())
});

/// Iron handler for authentication requests from the RP.
///
/// Calls the `oidc::request()` function if the provided email address's
/// domain matches one of the configured famous providers. Otherwise, calls the
/// `email::request()` function to allow authentication through the email loop.
broker_handler!(AuthHandler, |app, req| {
    let params = try!(
        match req.method {
            Method::Get => {
                req.compute::<UrlEncodedQuery>()
                    .map_err(|_| BrokerError::Input("no query string in GET request".to_string()))
            },
            Method::Post => {
                req.compute::<UrlEncodedBody>()
                    .map_err(|_| BrokerError::Input("no query string in POST data".to_string()))
            },
            _ => {
                panic!("Unsupported method: {}", req.method)
            }
        }
    );

    // Per the OAuth2 spec, we may redirect to the RP once we have validated client_id and
    // redirect_uri. In our case, this means we make redirect_uri available to error handling.
    let client_id = try_get_param!(params, "client_id");
    let redirect_uri = try!(
        Url::parse(try_get_param!(params, "redirect_uri"))
            .map_err(|_| BrokerError::Input("redirect_uri is not a valid URL".to_string()))
    );
    req.extensions.insert::<RedirectUri>(redirect_uri.clone());

    if try_get_param!(params, "response_type") != "id_token" {
        return Err(BrokerError::Input("unsupported response_type, only id_token is supported".to_string()));
    }
    if try_get_param!(params, "response_mode", "fragment") != "form_post" {
        return Err(BrokerError::Input("unsupported response_mode, only form_post is supported".to_string()))
    }
    let email_addr = try!(
        EmailAddress::new(try_get_param!(params, "login_hint"))
            .map_err(|_| BrokerError::Input("login_hint is not a valid email address".to_string()))
    );
    let nonce = try_get_param!(params, "nonce");
    if app.providers.contains_key(&email_addr.domain) {

        // OIDC authentication. Redirect to the identity provider.
        let auth_url = try!(oidc::request(app, email_addr, client_id, nonce, &redirect_uri));
        Ok(Response::with((status::SeeOther, modifiers::Header(Location(auth_url.to_string())))))

    } else {

        // Email loop authentication. Render a message and form.
        let session_id = try!(email::request(app, email_addr, client_id, nonce, &redirect_uri));
        Ok(Response::with((status::Ok,
                           modifiers::Header(ContentType::html()),
                           app.templates.confirm_email.render(&[
                               ("client_id", &client_id),
                               ("session_id", &session_id),
                           ]))))

    }
});

/// Helper method to create a JWT for a given email address and origin.
///
/// Builds the JSON payload, then signs it using the last key provided in
/// the configuration object.
fn create_jwt(app: &Config, email: &str, origin: &str, nonce: &str) -> String {
    let now = now_utc().to_timespec().sec;
    let payload = &ObjectBuilder::new()
        .insert("aud", origin)
        .insert("email", email)
        .insert("email_verified", email)
        .insert("exp", now + app.token_ttl as i64)
        .insert("iat", now)
        .insert("iss", &app.public_url)
        .insert("sub", email)
        .insert("nonce", nonce)
        .build();
    app.keys.last().unwrap().sign_jws(payload)
}

/// Iron handler for one-time pad email loop confirmation.
///
/// Retrieves the session based session ID and the expected one-time pad.
/// Verify the code and return the resulting token or error to the RP.
broker_handler!(ConfirmHandler, |app, req| {
    let params = try!(
        req.compute::<UrlEncodedQuery>()
            .map_err(|_| BrokerError::Input("no query string in GET request".to_string()))
    );

    let stored = try!(app.store.get_session("email", &try_get_param!(params, "session")));
    req.extensions.insert::<RedirectUri>(Url::parse(&stored["redirect"]).unwrap());

    let code = try_get_param!(params, "code");
    let (jwt, redirect_uri) = try!(email::verify(app, &stored, code));
    Ok(Response::with(return_to_relier(app, &redirect_uri, &[("id_token", &jwt)])))
});

/// Iron handler for OAuth callbacks
///
/// After the user allows or denies the Authentication Request with the famous
/// identity provider, they will be redirected back to the callback handler.
/// Verify the callback data and return the resulting token or error.
broker_handler!(CallbackHandler, |app, req| {
    let params = try!(
        req.compute::<UrlEncodedQuery>()
            .map_err(|_| BrokerError::Input("no query string in GET request".to_string()))
    );

    let stored = try!(app.store.get_session("oidc", &try_get_param!(params, "state")));
    req.extensions.insert::<RedirectUri>(Url::parse(&stored["redirect"]).unwrap());

    let code = try_get_param!(params, "code");
    let (jwt, redirect_uri) = try!(oidc::verify(app, &stored, code));
    Ok(Response::with(return_to_relier(app, &redirect_uri, &[("id_token", &jwt)])))
});
<|endoftext|>


<commit_before>#![feature(box_syntax, box_patterns)]

extern crate nibble_vec;

pub use nibble_vec::NibbleVec;
pub use keys::TrieKey;
use std::fmt::Debug;
use keys::{match_keys, check_keys, KeyMatch};
use DeleteAction::*;

mod keys;
#[cfg(test)]
mod test;

const BRANCH_FACTOR: usize = 16;

macro_rules! no_children {
    () => ([
        None, None, None, None,
        None, None, None, None,
        None, None, None, None,
        None, None, None, None
    ])
}

#[derive(Debug)]
pub struct Trie<K, V> {
    root: TrieNode<K, V>,
    length: usize
}

#[derive(Debug)]
struct TrieNode<K, V> {
    key: NibbleVec,
    key_value: Option<KeyValue<K, V>>,
    children: [Option<Box<TrieNode<K, V>>>; BRANCH_FACTOR],
    child_count: usize
}

#[derive(Debug)]
struct KeyValue<K, V> {
    key: K,
    value: V
}

#[derive(Debug)]
enum DeleteAction<K, V> {
    Replace(Box<TrieNode<K, V>>),
    Delete,
    DoNothing
}

impl<K, V> Trie<K, V> where K: TrieKey, V: Debug {
    pub fn new() -> Trie<K, V> {
        Trie {
            root: TrieNode {
                key: NibbleVec::new(),
                key_value: None,
                children: no_children![],
                child_count: 0
            },
            length: 0
        }
    }

    pub fn len(&self) -> usize {
        self.length
    }

    pub fn is_empty(&self) -> bool {
        self.length == 0
    }

    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
        let key_fragments = NibbleVec::from_byte_vec(key.encode());
        let result = self.root.insert(key, value, key_fragments);

        if result.is_none() {
            self.length += 1;
        }

        result
    }

    pub fn remove(&mut self, key: &K) -> Option<V> {
        let key_fragments = NibbleVec::from_byte_vec(key.encode());

        // Use the TrieNode recursive removal function but ignore its delete action.
        // The root can't be replaced or deleted.
        let (result, _) = self.root.remove_recursive(key, key_fragments);

        result
    }

    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
        let key_fragments = NibbleVec::from_byte_vec(key.encode());
        get_mut(&mut self.root, key, key_fragments)
    }

    pub fn get(&mut self, key: &K) -> Option<&V> {
        let key_fragments = NibbleVec::from_byte_vec(key.encode());
        get(&self.root, key, key_fragments)
    }
}

/// Identity macro to allow expansion of mutability token tree.
macro_rules! id {
    ($e:item) => { $e }
}

/// Macro to parametrise over mutability in get methods.
macro_rules! get_function {
    (
        name: $name:ident,
        mutability: $($mut_:tt)*
    ) => {
    id!(fn $name<'a, K, V>(
            trie: &'a $($mut_)* TrieNode<K, V>,
            key: &K,
            mut key_fragments: NibbleVec)
            -> Option<&'a $($mut_)* V> where K: TrieKey {

            let bucket = key_fragments.get(0) as usize;

            match trie.children[bucket] {
                None => None,
                Some(box ref $($mut_)* existing_child) => {
                    match match_keys(&key_fragments, &existing_child.key) {
                        KeyMatch::Full => {
                            match existing_child.key_value {
                                Some(ref $($mut_)* kv) => {
                                    assert_eq!(&kv.key, key);
                                    Some(& $($mut_)* kv.value)
                                },
                                None => None
                            }
                        },

                        KeyMatch::Partial(idx) => {
                            let new_key_fragments = key_fragments.split(idx);

                            $name(existing_child, key, new_key_fragments)
                        },

                        KeyMatch::FirstPrefix => None,

                        KeyMatch::SecondPrefix => {
                            let prefix_length = existing_child.key.len();
                            let new_key_fragments = key_fragments.split(prefix_length);

                            $name(existing_child, key, new_key_fragments)
                        }
                    }
                }
            }
        });
    }
}

get_function!(name: get_mut, mutability: mut);
get_function!(name: get, mutability: );

impl<K, V> TrieNode<K, V> where K: TrieKey, V: Debug {
    /// Create a node with no children.
    fn new(key_fragments: NibbleVec, key: K, value: V) -> TrieNode<K, V> {
        TrieNode {
            key: key_fragments,
            key_value: Some(KeyValue { key: key, value: value }),
            children: no_children![],
            child_count: 0
        }
    }

    /// Insert a given key and value below the current node.
    /// Let `key_fragments` be the bits of the key which are valid for insertion *below*
    /// the current node such that the 0th element of `key_fragments` describes the bucket
    /// that this key would be inserted into.
    fn insert(&mut self, key: K, value: V, mut key_fragments: NibbleVec) -> Option<V> {
        let bucket = key_fragments.get(0) as usize;

        match self.children[bucket] {
            // Case 1: No match. Simply insert.
            None => {
                self.children[bucket] = Some(Box::new(TrieNode::new(key_fragments, key, value)));
                self.child_count += 1;
                None
            }

            Some(box ref mut existing_child) => {
                match match_keys(&key_fragments, &existing_child.key) {
                    // Case 2: Full key match. Replace existing.
                    KeyMatch::Full => {
                        let result = match existing_child.key_value.take() {
                            Some(kv) => {
                                check_keys(&kv.key, &key);
                                Some(kv.value)
                            },
                            None => None
                        };

                        existing_child.key_value = Some(KeyValue { key: key, value: value });

                        result
                    }

                    // Case 3: Partial key match.
                    // Split the existing node's key, insert a new child for the second half of the
                    // key and insert the new key as a new child, with the prefix stripped.
                    KeyMatch::Partial(idx) => {
                        // Split the existing child.
                        existing_child.split(idx);

                        // Insert the new key below the prefix node.
                        let new_key = key_fragments.split(idx);
                        let new_key_bucket = new_key.get(0) as usize;

                        existing_child.children[new_key_bucket] = Some(Box::new(
                            TrieNode::new(new_key, key, value)
                        ));
                        existing_child.child_count += 1;

                        None
                    }

                    // Case 4: Existing key is a prefix.
                    // Strip the prefix and insert below the existing child (recurse).
                    KeyMatch::SecondPrefix => {
                        let prefix_length = existing_child.key.len();
                        let new_key_tail = key_fragments.split(prefix_length);

                        existing_child.insert(key, value, new_key_tail)
                    }

                    // Case 5: Key to insert is a prefix of the existing one.
                    // Split the existing child and place its value below the new one.
                    KeyMatch::FirstPrefix => {
                        existing_child.split(key_fragments.len());

                        existing_child.key_value = Some(KeyValue { key: key, value: value });

                        None
                    }
                }
            }
        }
    }

    fn remove_recursive(&mut self, key: &K, mut key_fragments: NibbleVec)
        -> (Option<V>, DeleteAction<K, V>) {

        let bucket = key_fragments.get(0) as usize;

        let (value, delete_action) = match self.children[bucket] {
            // Case 1: Not found, nothing to remove.
            None => return (None, DoNothing),

            Some(box ref mut existing_child) => {
                match match_keys(&key_fragments, &existing_child.key) {
                    // Case 2: Node found.
                    KeyMatch::Full => {
                        match existing_child.key_value.take() {
                            // Case 2a: Key found, pass the value up and delete the node.
                            Some(KeyValue { key: ex_key, value }) => {
                                check_keys(key, &ex_key);

                                println!("At the bottom.");
                                (Some(value), existing_child.delete_node())
                            }

                            // Case 2b: Key not found, nothing to remove.
                            None => return (None, DoNothing)
                        }
                    }

                    // Case 3: Recurse down.
                    KeyMatch::SecondPrefix => {
                        let prefix_length = existing_child.key.len();
                        let new_key_tail = key_fragments.split(prefix_length);

                        println!("Recursing down.");
                        existing_child.remove_recursive(key, new_key_tail)
                    }

                    // Case 4: Not found, nothing to remove.
                    KeyMatch::Partial(_) | KeyMatch::FirstPrefix => return (None, DoNothing)
                }
            }
        };

        println!("value is {:?}, delete action is {:?}", value, delete_action);

        // Apply the computed delete action.
        match delete_action {
            Replace(node) => {
                self.children[bucket] = Some(node);
                (value, DoNothing)
            }

            Delete => {
                self.children[bucket] = None;
                self.child_count -= 1;

                // The removal of a child could cause this node to be replaced or deleted.
                (value, self.delete_node())
            }

            DoNothing => (value, DoNothing)
        }
    }

    /// Having removed the value from a node, work out if the node itself should be deleted.
    /// Depending on the number of children, this method does one of three things.
    ///     0 children => return true
    ///     1 child => compress the child into this node, return false
    ///     2 or more children => return false
    fn delete_node(&mut self) -> DeleteAction<K, V> {

        // Helper function for getting the single child of a node.
        fn get_child<K, V>(node: &mut TrieNode<K, V>) -> Box<TrieNode<K, V>> {
            for i in 0 .. BRANCH_FACTOR {
                match node.children[i].take() {
                    Some(child) => {
                        node.child_count -= 1;
                        return child;
                    }
                    None => ()
                }
            }
            unreachable!("node with child_count 1 has no actual children");
        }

        match self.child_count {
            0 if self.key_value.is_some() => DoNothing,
            0 => Delete,
            1 => {
                let mut child = get_child(self);

                // Join the child's key onto the existing one.
                let mut new_key = self.key.clone();
                new_key.join(&child.key);

                child.key = new_key;

                Replace(child)
            }
            _ => DoNothing
        }
    }

    /// Split a node at a given index in its key, transforming it into a prefix node of its
    /// previous self.
    fn split(&mut self, idx: usize) {
        // Extract all the parts of the suffix node, starting with the key.
        let key = self.key.split(idx);

        // Key-value.
        let key_value = self.key_value.take();

        // Children.
        let mut children = no_children![];

        for (i, child) in self.children.iter_mut().enumerate() {
            if child.is_some() {
                children[i] = child.take();
            }
        }

        // Child count.
        let child_count = self.child_count;
        self.child_count = 1;

        // Insert the collected items below what is now an empty prefix node.
        let bucket = key.get(0) as usize;
        self.children[bucket] = Some(Box::new(
            TrieNode {
                key: key,
                key_value: key_value,
                children: children,
                child_count: child_count
            }
        ));
    }
}
<commit_msg>Clean-up some remove code.<commit_after>#![feature(box_syntax, box_patterns)]

extern crate nibble_vec;

pub use nibble_vec::NibbleVec;
pub use keys::TrieKey;
use keys::{match_keys, check_keys, KeyMatch};
use DeleteAction::*;

mod keys;
#[cfg(test)]
mod test;

const BRANCH_FACTOR: usize = 16;

macro_rules! no_children {
    () => ([
        None, None, None, None,
        None, None, None, None,
        None, None, None, None,
        None, None, None, None
    ])
}

#[derive(Debug)]
pub struct Trie<K, V> {
    root: TrieNode<K, V>,
    length: usize
}

#[derive(Debug)]
struct TrieNode<K, V> {
    key: NibbleVec,
    key_value: Option<KeyValue<K, V>>,
    children: [Option<Box<TrieNode<K, V>>>; BRANCH_FACTOR],
    child_count: usize
}

#[derive(Debug)]
struct KeyValue<K, V> {
    key: K,
    value: V
}

#[derive(Debug)]
enum DeleteAction<K, V> {
    Replace(Box<TrieNode<K, V>>),
    Delete,
    DoNothing
}

impl<K, V> Trie<K, V> where K: TrieKey {
    pub fn new() -> Trie<K, V> {
        Trie {
            root: TrieNode {
                key: NibbleVec::new(),
                key_value: None,
                children: no_children![],
                child_count: 0
            },
            length: 0
        }
    }

    pub fn len(&self) -> usize {
        self.length
    }

    pub fn is_empty(&self) -> bool {
        self.length == 0
    }

    pub fn get(&mut self, key: &K) -> Option<&V> {
        let key_fragments = NibbleVec::from_byte_vec(key.encode());
        get(&self.root, key, key_fragments)
    }

    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
        let key_fragments = NibbleVec::from_byte_vec(key.encode());
        get_mut(&mut self.root, key, key_fragments)
    }

    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
        let key_fragments = NibbleVec::from_byte_vec(key.encode());
        let result = self.root.insert(key, value, key_fragments);

        if result.is_none() {
            self.length += 1;
        }

        result
    }

    pub fn remove(&mut self, key: &K) -> Option<V> {
        let key_fragments = NibbleVec::from_byte_vec(key.encode());

        // Use the TrieNode recursive removal function but ignore its delete action.
        // The root can't be replaced or deleted.
        let (result, _) = self.root.remove_recursive(key, key_fragments);

        if result.is_some() {
            self.length -= 1;
        }

        result
    }
}

/// Identity macro to allow expansion of mutability token tree.
macro_rules! id {
    ($e:item) => { $e }
}

/// Macro to parametrise over mutability in get methods.
macro_rules! get_function {
    (
        name: $name:ident,
        mutability: $($mut_:tt)*
    ) => {
    id!(fn $name<'a, K, V>(
            trie: &'a $($mut_)* TrieNode<K, V>,
            key: &K,
            mut key_fragments: NibbleVec)
            -> Option<&'a $($mut_)* V> where K: TrieKey {

            let bucket = key_fragments.get(0) as usize;

            match trie.children[bucket] {
                None => None,
                Some(box ref $($mut_)* existing_child) => {
                    match match_keys(&key_fragments, &existing_child.key) {
                        KeyMatch::Full => {
                            match existing_child.key_value {
                                Some(ref $($mut_)* kv) => {
                                    assert_eq!(&kv.key, key);
                                    Some(& $($mut_)* kv.value)
                                },
                                None => None
                            }
                        },

                        KeyMatch::Partial(idx) => {
                            let new_key_fragments = key_fragments.split(idx);

                            $name(existing_child, key, new_key_fragments)
                        },

                        KeyMatch::FirstPrefix => None,

                        KeyMatch::SecondPrefix => {
                            let prefix_length = existing_child.key.len();
                            let new_key_fragments = key_fragments.split(prefix_length);

                            $name(existing_child, key, new_key_fragments)
                        }
                    }
                }
            }
        });
    }
}

get_function!(name: get_mut, mutability: mut);
get_function!(name: get, mutability: );

impl<K, V> TrieNode<K, V> where K: TrieKey {
    /// Create a node with no children.
    fn new(key_fragments: NibbleVec, key: K, value: V) -> TrieNode<K, V> {
        TrieNode {
            key: key_fragments,
            key_value: Some(KeyValue { key: key, value: value }),
            children: no_children![],
            child_count: 0
        }
    }

    /// Add a child at the given index, assuming none exists already.
    fn add_child(&mut self, idx: usize, node: Box<TrieNode<K, V>>) {
        self.children[idx] = Some(node);
        self.child_count += 1;
    }

    /// Remove a child at the given index, if it exists.
    fn take_child(&mut self, idx: usize) -> Option<Box<TrieNode<K, V>>> {
        self.children[idx].take().map(|node| { self.child_count -= 1; node })
    }

    /// Helper function for removing the single child of a node.
    fn take_only_child(&mut self) -> Box<TrieNode<K, V>> {
        for i in 0 .. BRANCH_FACTOR {
            match self.take_child(i) {
                Some(child) => return child,
                None => ()
            }
        }
        unreachable!("node with child_count 1 has no actual children");
    }

    /// Insert a given key and value below the current node.
    /// Let `key_fragments` be the bits of the key which are valid for insertion *below*
    /// the current node such that the 0th element of `key_fragments` describes the bucket
    /// that this key would be inserted into.
    fn insert(&mut self, key: K, value: V, mut key_fragments: NibbleVec) -> Option<V> {
        let bucket = key_fragments.get(0) as usize;

        match self.children[bucket] {
            // Case 1: No match. Simply insert.
            None => {
                self.add_child(bucket, Box::new(TrieNode::new(key_fragments, key, value)));
                None
            }

            Some(box ref mut existing_child) => {
                match match_keys(&key_fragments, &existing_child.key) {
                    // Case 2: Full key match. Replace existing.
                    KeyMatch::Full => {
                        let result = existing_child.key_value.take().map(|kv| {
                            check_keys(&kv.key, &key);
                            kv.value
                        });

                        existing_child.key_value = Some(KeyValue { key: key, value: value });

                        result
                    }

                    // Case 3: Partial key match.
                    // Split the existing node's key, insert a new child for the second half of the
                    // key and insert the new key as a new child, with the prefix stripped.
                    KeyMatch::Partial(idx) => {
                        // Split the existing child.
                        existing_child.split(idx);

                        // Insert the new key below the prefix node.
                        let new_key = key_fragments.split(idx);
                        let new_key_bucket = new_key.get(0) as usize;

                        existing_child.add_child(
                            new_key_bucket,
                            Box::new(TrieNode::new(new_key, key, value))
                        );

                        None
                    }

                    // Case 4: Existing key is a prefix.
                    // Strip the prefix and insert below the existing child (recurse).
                    KeyMatch::SecondPrefix => {
                        let prefix_length = existing_child.key.len();
                        let new_key_tail = key_fragments.split(prefix_length);

                        existing_child.insert(key, value, new_key_tail)
                    }

                    // Case 5: Key to insert is a prefix of the existing one.
                    // Split the existing child and place its value below the new one.
                    KeyMatch::FirstPrefix => {
                        existing_child.split(key_fragments.len());

                        existing_child.key_value = Some(KeyValue { key: key, value: value });

                        None
                    }
                }
            }
        }
    }

    fn remove_recursive(&mut self, key: &K, mut key_fragments: NibbleVec)
        -> (Option<V>, DeleteAction<K, V>) {

        let bucket = key_fragments.get(0) as usize;

        let (value, delete_action) = match self.children[bucket] {
            // Case 1: Not found, nothing to remove.
            None => return (None, DoNothing),

            Some(box ref mut existing_child) => {
                match match_keys(&key_fragments, &existing_child.key) {
                    // Case 2: Node found.
                    KeyMatch::Full => {
                        match existing_child.key_value.take() {
                            // Case 2a: Key found, pass the value up and delete the node.
                            Some(KeyValue { key: ex_key, value }) => {
                                check_keys(key, &ex_key);

                                (Some(value), existing_child.delete_node())
                            }

                            // Case 2b: Key not found, nothing to remove.
                            None => return (None, DoNothing)
                        }
                    }

                    // Case 3: Recurse down.
                    KeyMatch::SecondPrefix => {
                        let prefix_length = existing_child.key.len();
                        let new_key_tail = key_fragments.split(prefix_length);

                        existing_child.remove_recursive(key, new_key_tail)
                    }

                    // Case 4: Not found, nothing to remove.
                    KeyMatch::Partial(_) | KeyMatch::FirstPrefix => return (None, DoNothing)
                }
            }
        };

        // Apply the computed delete action.
        match delete_action {
            Replace(node) => {
                self.children[bucket] = Some(node);
                (value, DoNothing)
            }

            Delete => {
                self.take_child(bucket);

                // The removal of a child could cause this node to be replaced or deleted.
                (value, self.delete_node())
            }

            DoNothing => (value, DoNothing)
        }
    }

    /// Having removed the value from a node, work out if the node itself should be deleted.
    /// Depending on the number of children, this method does one of three things.
    ///     0 children => Delete the node if it is valueless, otherwise DoNothing.
    ///     1 child => Replace the current node by its child.
    ///     2 or more children => DoNothing.
    fn delete_node(&mut self) -> DeleteAction<K, V> {
        match self.child_count {
            0 if self.key_value.is_some() => DoNothing,
            0 => Delete,
            1 => {
                let mut child = self.take_only_child();

                // Join the child's key onto the existing one.
                let mut new_key = self.key.clone();
                new_key.join(&child.key);

                child.key = new_key;

                Replace(child)
            }
            _ => DoNothing
        }
    }

    /// Split a node at a given index in its key, transforming it into a prefix node of its
    /// previous self.
    fn split(&mut self, idx: usize) {
        // Extract all the parts of the suffix node, starting with the key.
        let key = self.key.split(idx);

        // Key-value.
        let key_value = self.key_value.take();

        // Children.
        let mut children = no_children![];

        for (i, child) in self.children.iter_mut().enumerate() {
            if child.is_some() {
                children[i] = child.take();
            }
        }

        // Child count.
        let child_count = self.child_count;
        self.child_count = 1;

        // Insert the collected items below what is now an empty prefix node.
        let bucket = key.get(0) as usize;
        self.children[bucket] = Some(Box::new(
            TrieNode {
                key: key,
                key_value: key_value,
                children: children,
                child_count: child_count
            }
        ));
    }
}
<|endoftext|>


<commit_before>//! A memory-safer wrapper around system dynamic library primitives.
//!
//! With this library you can load [dynamic libraries](struct.Library.html) and retrieve
//! [symbols](struct.Symbol.html) from the loaded libraries.
//!
//! Less safe platform specific bindings are available in the [`os::platform`](os/index.html)
//! modules.
use std::ffi::OsStr;
use std::fmt;
use std::marker;

#[cfg(unix)]
#[macro_use]
extern crate lazy_static;

#[cfg(unix)]
use self::os::unix as imp;
#[cfg(windows)]
use self::os::windows as imp;

pub mod os;
mod util;

pub type Result<T> = ::std::io::Result<T>;

/// A dynamically loaded library.
pub struct Library(imp::Library);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # use ::libloading::Library;
    /// // on Unix
    /// let lib = Library::new("libm.so.6").unwrap();
    /// // on OS X
    /// let lib = Library::new("libm.dylib").unwrap();
    /// // on Windows
    /// let lib = Library::new("msvcrt.dll").unwrap();
    /// ```
    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library> {
        imp::Library::new(filename).map(Library)
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    ///
    /// # Examples
    ///
    /// Simple function:
    ///
    /// ```no_run
    /// # use ::libloading::{ Library, Symbol };
    /// # let lib = Library::new("libm.so.6").unwrap();
    /// let sin: Symbol<unsafe extern fn(f64) -> f64> = unsafe {
    ///     lib.get(b"sin\0").unwrap()
    /// };
    /// ```
    ///
    /// A static or TLS variable:
    ///
    /// ```no_run
    /// # use ::libloading::{ Library, Symbol };
    /// # let lib = Library::new("libm.so.6").unwrap();
    /// let errno: Symbol<*mut u32> = unsafe {
    ///     lib.get(b"errno\0").unwrap()
    /// };
    /// ```
    pub unsafe fn get<'lib, T>(&'lib self, symbol: &[u8]) -> Result<Symbol<'lib, T>> {
        self.0.get(symbol).map(|from| {
            Symbol {
                inner: from,
                pd: marker::PhantomData
            }
        })
    }
}

impl fmt::Debug for Library {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// Symbol from a library.
///
/// This type is a safeguard against using dynamically loaded symbols after a `Library` is
/// unloaded. Primary method to create an instance of a `Symbol` is via `Library::get`.
///
/// Due to implementation of the `Deref` trait, an instance of `Symbol` may be used as if it was a
/// function or variable directly, without taking care to “extract” function or variable manually
/// most of the time.
///
/// # Examples
///
/// ```
/// # #[cfg(all(unix, not(any(target_os="macos", target_os="ios", target_os="android"))))]
/// # fn main() {
/// #     use ::libloading::{ Library, Symbol };
/// #     let lib = Library::new("libm.so.6").unwrap();
/// let sin: Symbol<unsafe extern fn(f64) -> f64> = unsafe {
///     lib.get(b"sin\0").unwrap()
/// };
///
/// let sine0 = unsafe { sin(0f64) };
/// assert!(sine0 < 0.1E-10);
/// # }
/// ```
pub struct Symbol<'lib, T: 'lib> {
    inner: imp::Symbol<T>,
    pd: marker::PhantomData<&'lib T>
}

impl<'lib, T> ::std::ops::Deref for Symbol<'lib, T> {
    type Target = T;
    fn deref(&self) -> &T {
        ::std::ops::Deref::deref(&self.inner)
    }
}

impl<'lib, T> fmt::Debug for Symbol<'lib, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.inner.fmt(f)
    }
}

#[cfg(all(unix, not(any(target_os="macos", target_os="ios", target_os="android"))))]
#[test]
fn libm() {
    let lib = Library::new("libm.so.6").unwrap();
    let sin: Symbol<unsafe extern fn(f64) -> f64> = unsafe {
        lib.get(b"sin").unwrap()
    };
    assert!(unsafe { sin(::std::f64::INFINITY) }.is_nan());
    let errno: Symbol<*mut u32> = unsafe {
        lib.get(b"errno").unwrap()
    };
    assert!(unsafe { **errno } != 0);
    unsafe { **errno = 0; }
}
<commit_msg>Change Symbol doc test to no_run<commit_after>//! A memory-safer wrapper around system dynamic library primitives.
//!
//! With this library you can load [dynamic libraries](struct.Library.html) and retrieve
//! [symbols](struct.Symbol.html) from the loaded libraries.
//!
//! Less safe platform specific bindings are available in the [`os::platform`](os/index.html)
//! modules.
use std::ffi::OsStr;
use std::fmt;
use std::marker;

#[cfg(unix)]
#[macro_use]
extern crate lazy_static;

#[cfg(unix)]
use self::os::unix as imp;
#[cfg(windows)]
use self::os::windows as imp;

pub mod os;
mod util;

pub type Result<T> = ::std::io::Result<T>;

/// A dynamically loaded library.
pub struct Library(imp::Library);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # use ::libloading::Library;
    /// // on Unix
    /// let lib = Library::new("libm.so.6").unwrap();
    /// // on OS X
    /// let lib = Library::new("libm.dylib").unwrap();
    /// // on Windows
    /// let lib = Library::new("msvcrt.dll").unwrap();
    /// ```
    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library> {
        imp::Library::new(filename).map(Library)
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    ///
    /// # Examples
    ///
    /// Simple function:
    ///
    /// ```no_run
    /// # use ::libloading::{ Library, Symbol };
    /// # let lib = Library::new("libm.so.6").unwrap();
    /// let sin: Symbol<unsafe extern fn(f64) -> f64> = unsafe {
    ///     lib.get(b"sin\0").unwrap()
    /// };
    /// ```
    ///
    /// A static or TLS variable:
    ///
    /// ```no_run
    /// # use ::libloading::{ Library, Symbol };
    /// # let lib = Library::new("libm.so.6").unwrap();
    /// let errno: Symbol<*mut u32> = unsafe {
    ///     lib.get(b"errno\0").unwrap()
    /// };
    /// ```
    pub unsafe fn get<'lib, T>(&'lib self, symbol: &[u8]) -> Result<Symbol<'lib, T>> {
        self.0.get(symbol).map(|from| {
            Symbol {
                inner: from,
                pd: marker::PhantomData
            }
        })
    }
}

impl fmt::Debug for Library {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// Symbol from a library.
///
/// This type is a safeguard against using dynamically loaded symbols after a `Library` is
/// unloaded. Primary method to create an instance of a `Symbol` is via `Library::get`.
///
/// Due to implementation of the `Deref` trait, an instance of `Symbol` may be used as if it was a
/// function or variable directly, without taking care to “extract” function or variable manually
/// most of the time.
///
/// # Examples
///
/// ```no_run
/// # use ::libloading::{ Library, Symbol };
/// # let lib = Library::new("libm.so.6").unwrap();
/// let sin: Symbol<unsafe extern fn(f64) -> f64> = unsafe {
///     lib.get(b"sin\0").unwrap()
/// };
///
/// let sine0 = unsafe { sin(0f64) };
/// assert!(sine0 < 0.1E-10);
/// ```
pub struct Symbol<'lib, T: 'lib> {
    inner: imp::Symbol<T>,
    pd: marker::PhantomData<&'lib T>
}

impl<'lib, T> ::std::ops::Deref for Symbol<'lib, T> {
    type Target = T;
    fn deref(&self) -> &T {
        ::std::ops::Deref::deref(&self.inner)
    }
}

impl<'lib, T> fmt::Debug for Symbol<'lib, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.inner.fmt(f)
    }
}

#[cfg(all(unix, not(any(target_os="macos", target_os="ios", target_os="android"))))]
#[test]
fn libm() {
    let lib = Library::new("libm.so.6").unwrap();
    let sin: Symbol<unsafe extern fn(f64) -> f64> = unsafe {
        lib.get(b"sin").unwrap()
    };
    assert!(unsafe { sin(::std::f64::INFINITY) }.is_nan());
    let errno: Symbol<*mut u32> = unsafe {
        lib.get(b"errno").unwrap()
    };
    assert!(unsafe { **errno } != 0);
    unsafe { **errno = 0; }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
mod ansi;
mod engine;
mod event;
mod field;
mod header;
mod input;
mod item;
mod matcher;
mod model;
mod options;
mod orderedvec;
mod output;
mod previewer;
mod query;
mod reader;
mod score;
mod selection;
mod spinlock;
mod theme;
mod util;

use crate::event::Event::*;
use crate::event::{EventReceiver, EventSender};
use crate::model::Model;
pub use crate::options::{SkimOptions, SkimOptionsBuilder};
pub use crate::output::SkimOutput;
use crate::reader::Reader;
use nix::unistd::isatty;
use std::env;
use std::io::BufRead;
use std::io::BufReader;
use std::os::unix::io::AsRawFd;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use tuikit::term::{Term, TermHeight, TermOptions};

const REFRESH_DURATION: u64 = 25;

pub struct Skim {}

impl Skim {
    pub fn run_with(options: &SkimOptions, source: Option<Box<BufRead + Send>>) -> Option<SkimOutput> {
        let min_height = options
            .min_height
            .map(Skim::parse_height_string)
            .expect("min_height should have default values");
        let height = options
            .height
            .map(Skim::parse_height_string)
            .expect("height should have default values");

        let (tx, rx): (EventSender, EventReceiver) = channel();
        let term = Arc::new(Term::with_options(TermOptions::default().min_height(min_height).height(height)).unwrap());

        //------------------------------------------------------------------------------
        // input
        let mut input = input::Input::new();
        input.parse_keymaps(&options.bind);
        input.parse_expect_keys(options.expect.as_ref().map(|x| &**x));
        let tx_clone = tx.clone();
        let term_clone = term.clone();
        thread::spawn(move || 'outer: loop {
            if let Ok(key) = term_clone.poll_event() {
                for (ev, arg) in input.translate_event(key).into_iter() {
                    let _ = tx_clone.send((ev, arg));
                    if ev == EvActAccept || ev == EvActAbort {
                        break 'outer;
                    }
                }
            }
        });

        //------------------------------------------------------------------------------
        // reader

        // in piped situation(e.g. `echo "a" | sk`) set source to the pipe
        let source = source.or_else(|| {
            let stdin = std::io::stdin();
            if !isatty(stdin.as_raw_fd()).unwrap_or(true) {
                Some(Box::new(BufReader::new(stdin)))
            } else {
                None
            }
        });

        let reader = Reader::with_options(&options).source(source);

        //------------------------------------------------------------------------------
        // start a timer for notifying refresh
        let tx_clone = tx.clone();
        thread::spawn(move || loop {
            let _ = tx_clone.send((EvHeartBeat, Box::new(true)));
            thread::sleep(Duration::from_millis(REFRESH_DURATION));
        });

        //------------------------------------------------------------------------------
        // model + previewer
        let mut model = Model::new(rx, tx, reader, term, &options);
        model.start()
    }

    pub fn filter(options: &SkimOptions, source: Option<Box<BufRead + Send>>) -> i32 {
        use engine::{EngineFactory, MatcherMode};

        let output_ending = if options.print0 { "\0" } else { "\n" };
        let query = options.filter;
        let default_command = match env::var("SKIM_DEFAULT_COMMAND").as_ref().map(String::as_ref) {
            Ok("") | Err(_) => "find .".to_owned(),
            Ok(val) => val.to_owned(),
        };

        let cmd = options.cmd.unwrap_or(&default_command);

        // output query
        if options.print_query {
            print!("{}{}", query, output_ending);
        }

        if options.print_cmd {
            print!("{}{}", cmd, output_ending);
        }

        //------------------------------------------------------------------------------
        // reader

        // in piped situation(e.g. `echo "a" | sk`) set source to the pipe
        let source = source.or_else(|| {
            let stdin = std::io::stdin();
            if !isatty(stdin.as_raw_fd()).unwrap_or(true) {
                Some(Box::new(BufReader::new(stdin)))
            } else {
                None
            }
        });

        let mut reader = Reader::with_options(&options).source(source);

        //------------------------------------------------------------------------------
        // matcher
        let matcher_mode = if options.regex {
            MatcherMode::Regex
        } else if options.exact {
            MatcherMode::Exact
        } else {
            MatcherMode::Fuzzy
        };

        let engine = EngineFactory::build(query, matcher_mode);

        //------------------------------------------------------------------------------
        // start
        let reader_control = reader.run(cmd);

        let mut match_count = 0;
        while !reader_control.is_done() {
            for item in reader_control.take().into_iter() {
                if let Some(matched) = engine.match_item(item) {
                    println!("{}\t{}", -matched.rank.score, matched.item.get_output_text());
                    match_count += 1;
                }
            }
        }

        if match_count == 0 {
            return 1;
        } else {
            return 0;
        }
    }

    // 10 -> TermHeight::Fixed(10)
    // 10% -> TermHeight::Percent(10)
    fn parse_height_string(string: &str) -> TermHeight {
        if string.ends_with('%') {
            TermHeight::Percent(string[0..string.len() - 1].parse().unwrap_or(100))
        } else {
            TermHeight::Fixed(string.parse().unwrap_or(0))
        }
    }
}
<commit_msg>fix #153 failed to build with rust 2018<commit_after>#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
mod ansi;
mod engine;
mod event;
mod field;
mod header;
mod input;
mod item;
mod matcher;
mod model;
mod options;
mod orderedvec;
mod output;
mod previewer;
mod query;
mod reader;
mod score;
mod selection;
mod spinlock;
mod theme;
mod util;

use crate::event::Event::*;
use crate::event::{EventReceiver, EventSender};
use crate::model::Model;
pub use crate::options::{SkimOptions, SkimOptionsBuilder};
pub use crate::output::SkimOutput;
use crate::reader::Reader;
use nix::unistd::isatty;
use std::env;
use std::io::BufRead;
use std::io::BufReader;
use std::os::unix::io::AsRawFd;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use tuikit::term::{Term, TermHeight, TermOptions};

const REFRESH_DURATION: u64 = 25;

pub struct Skim {}

impl Skim {
    pub fn run_with(options: &SkimOptions, source: Option<Box<BufRead + Send>>) -> Option<SkimOutput> {
        let min_height = options
            .min_height
            .map(Skim::parse_height_string)
            .expect("min_height should have default values");
        let height = options
            .height
            .map(Skim::parse_height_string)
            .expect("height should have default values");

        let (tx, rx): (EventSender, EventReceiver) = channel();
        let term = Arc::new(Term::with_options(TermOptions::default().min_height(min_height).height(height)).unwrap());

        //------------------------------------------------------------------------------
        // input
        let mut input = input::Input::new();
        input.parse_keymaps(&options.bind);
        input.parse_expect_keys(options.expect.as_ref().map(|x| &**x));
        let tx_clone = tx.clone();
        let term_clone = term.clone();
        thread::spawn(move || 'outer: loop {
            if let Ok(key) = term_clone.poll_event() {
                for (ev, arg) in input.translate_event(key).into_iter() {
                    let _ = tx_clone.send((ev, arg));
                    if ev == EvActAccept || ev == EvActAbort {
                        break 'outer;
                    }
                }
            }
        });

        //------------------------------------------------------------------------------
        // reader

        // in piped situation(e.g. `echo "a" | sk`) set source to the pipe
        let source = source.or_else(|| {
            let stdin = std::io::stdin();
            if !isatty(stdin.as_raw_fd()).unwrap_or(true) {
                Some(Box::new(BufReader::new(stdin)))
            } else {
                None
            }
        });

        let reader = Reader::with_options(&options).source(source);

        //------------------------------------------------------------------------------
        // start a timer for notifying refresh
        let tx_clone = tx.clone();
        thread::spawn(move || loop {
            let _ = tx_clone.send((EvHeartBeat, Box::new(true)));
            thread::sleep(Duration::from_millis(REFRESH_DURATION));
        });

        //------------------------------------------------------------------------------
        // model + previewer
        let mut model = Model::new(rx, tx, reader, term, &options);
        model.start()
    }

    pub fn filter(options: &SkimOptions, source: Option<Box<BufRead + Send>>) -> i32 {
        use crate::engine::{EngineFactory, MatcherMode};

        let output_ending = if options.print0 { "\0" } else { "\n" };
        let query = options.filter;
        let default_command = match env::var("SKIM_DEFAULT_COMMAND").as_ref().map(String::as_ref) {
            Ok("") | Err(_) => "find .".to_owned(),
            Ok(val) => val.to_owned(),
        };

        let cmd = options.cmd.unwrap_or(&default_command);

        // output query
        if options.print_query {
            print!("{}{}", query, output_ending);
        }

        if options.print_cmd {
            print!("{}{}", cmd, output_ending);
        }

        //------------------------------------------------------------------------------
        // reader

        // in piped situation(e.g. `echo "a" | sk`) set source to the pipe
        let source = source.or_else(|| {
            let stdin = std::io::stdin();
            if !isatty(stdin.as_raw_fd()).unwrap_or(true) {
                Some(Box::new(BufReader::new(stdin)))
            } else {
                None
            }
        });

        let mut reader = Reader::with_options(&options).source(source);

        //------------------------------------------------------------------------------
        // matcher
        let matcher_mode = if options.regex {
            MatcherMode::Regex
        } else if options.exact {
            MatcherMode::Exact
        } else {
            MatcherMode::Fuzzy
        };

        let engine = EngineFactory::build(query, matcher_mode);

        //------------------------------------------------------------------------------
        // start
        let reader_control = reader.run(cmd);

        let mut match_count = 0;
        while !reader_control.is_done() {
            for item in reader_control.take().into_iter() {
                if let Some(matched) = engine.match_item(item) {
                    println!("{}\t{}", -matched.rank.score, matched.item.get_output_text());
                    match_count += 1;
                }
            }
        }

        if match_count == 0 {
            return 1;
        } else {
            return 0;
        }
    }

    // 10 -> TermHeight::Fixed(10)
    // 10% -> TermHeight::Percent(10)
    fn parse_height_string(string: &str) -> TermHeight {
        if string.ends_with('%') {
            TermHeight::Percent(string[0..string.len() - 1].parse().unwrap_or(100))
        } else {
            TermHeight::Fixed(string.parse().unwrap_or(0))
        }
    }
}
<|endoftext|>