<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+.
//!
//! This library provides a [`Widget`](trait.Widget.html) 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.3.0"
//! relm = "^0.11.0"
//! relm-derive = "^0.11.0"
//! ```
//!
//! More info can be found in the [readme](https://github.com/antoyo/relm#relm).

#![warn(
    missing_docs,
    trivial_casts,
    trivial_numeric_casts,
    unused_extern_crates,
    unused_import_braces,
    unused_qualifications,
)]

/*
 * TODO: maybe remove SimpleMsg.
 *
 * TODO: improve README so that examples can be copy/pasted.
 * TODO: add tests for relm-derive-state.
 *
 * FIXME: some relm widgets requires { and } (see the rusic music-player) while other do not.
 * FIXME: should not require to import WidgetExt because it calls show().
 * FIXME: cannot have relm event with tuple as a value like:
 * RelmWidget {
 *     RelmEvent((value1, value2)) => …
 * }
 * TODO: use pub(crate) instead of pub so that we're not bound to make the model and msg structs pub.
 *
 * TODO: add init() method to the Widget (or Update) trait as a shortcut for init::<Widget>()?
 *
 * TODO: alternative to tokio with a trait to get FD and add this FD to glib (perhaps using a
 * GSource).
 * For timers, add a connect_timeout!() macro or something.
 *
 * TODO: show a warning when a component is imediately destroyed.
 * FIXME: cannot add a trailing coma at the end of a initializer list.
 * TODO: switch from gtk::main() to MainLoop to avoid issues with nested loops.
 * TODO: prefix generated container name with _ to hide warnings.
 * TODO: remove the code generation related to using self in event handling.
 * TODO: remove the closure transformer code.
 *
 * TODO: move most of the examples in the tests/ directory.
 * 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: add a FAQ with the question related to getting an error when not importing the gtk traits.
 *
 * 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.
 */

extern crate cairo;
extern crate glib;
extern crate glib_sys;
extern crate gobject_sys;
extern crate gtk;
extern crate libc;
extern crate relm_core;
extern crate relm_state;

mod component;
mod container;
mod drawing;
mod macros;
mod widget;

#[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 gtk::Continue;
use libc::{c_char, c_uint};
#[doc(hidden)]
pub use relm_core::{Channel, EventStream};
pub use relm_state::{
    DisplayVariant,
    IntoOption,
    IntoPair,
    Relm,
    Update,
    UpdateNew,
    execute,
};
use relm_state::init_component;

pub use component::Component;
pub use container::{Container, ContainerComponent, ContainerWidget};
pub use drawing::DrawHandler;
pub use widget::{Widget, WidgetTest};

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 $(::relm::)*Widget for $self_type:ident { $($tts:tt)* }) => {
        pub use self::__relm_gen_private::$self_type;
    };
}

fn create_widget_test<WIDGET>(model_param: WIDGET::ModelParam) -> (Component<WIDGET>, WIDGET::Widgets)
    where WIDGET: Widget + WidgetTest + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    let (widget, component, relm): (_, WIDGET, _) = create_widget(model_param);
    let widgets = component.get_widgets();
    init_component::<WIDGET>(widget.stream(), component, &relm);
    (widget, widgets)
}

/// 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>(model_param: CHILDWIDGET::ModelParam)
        -> Component<CHILDWIDGET>
    where CHILDWIDGET: Widget + 'static,
          CHILDWIDGET::Msg: DisplayVariant + 'static,
{
    let (widget, component, child_relm) = create_widget::<CHILDWIDGET>(model_param);
    init_component::<CHILDWIDGET>(widget.stream(), component, &child_relm);
    widget
}

/// Create a new relm container 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_container<CHILDWIDGET>(model_param: CHILDWIDGET::ModelParam)
        -> ContainerComponent<CHILDWIDGET>
    where CHILDWIDGET: Container + Widget + 'static,
          CHILDWIDGET::Msg: DisplayVariant + 'static,
{
    let (widget, component, child_relm) = create_widget::<CHILDWIDGET>(model_param);
    let container = component.container().clone();
    let containers = component.other_containers();
    init_component::<CHILDWIDGET>(widget.stream(), component, &child_relm);
    ContainerComponent::new(widget, container, containers)
}

/// Create a new relm widget with `model_param` as initialization value.
fn create_widget<WIDGET>(model_param: WIDGET::ModelParam)
    -> (Component<WIDGET>, WIDGET, Relm<WIDGET>)
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    let stream = EventStream::new();

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

    let root = widget.root().clone();
    (Component::new(stream, root), widget, relm)
}

/// 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, Update, Widget, WidgetTest};
/// #
/// # #[derive(Clone)]
/// # struct Win {
/// #     window: Window,
/// # }
/// #
/// # impl Update for Win {
/// #     type Model = ();
/// #     type ModelParam = ();
/// #     type Msg = Msg;
/// #
/// #     fn model(_: &Relm<Self>, _: ()) -> () {
/// #         ()
/// #     }
/// #
/// #     fn update(&mut self, event: Msg) {
/// #     }
/// # }
/// #
/// # impl WidgetTest for Win {
/// #     type Widgets = Win;
/// #
/// #     fn get_widgets(&self) -> Self::Widgets {
/// #         self.clone()
/// #     }
/// # }
/// #
/// # impl Widget for Win {
/// #     type Root = Window;
/// #
/// #     fn root(&self) -> Self::Root {
/// #         self.window.clone()
/// #     }
/// #
/// #     fn view(relm: &Relm<Self>, _model: Self::Model) -> Self {
/// #         let window = Window::new(WindowType::Toplevel);
/// #
/// #         Win {
/// #             window: window,
/// #         }
/// #     }
/// # }
/// #
/// # #[derive(Msg)]
/// # enum Msg {}
/// # fn main() {
/// let (component, widgets) = relm::init_test::<Win>(()).unwrap();
/// # }
/// ```
pub fn init_test<WIDGET>(model_param: WIDGET::ModelParam) ->
    Result<(Component<WIDGET>, WIDGET::Widgets), ()>
    where WIDGET: Widget + WidgetTest + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    let component = create_widget_test::<WIDGET>(model_param);
    Ok(component)
}

/// Initialize a widget.
pub fn init<WIDGET>(model_param: WIDGET::ModelParam) -> Result<Component<WIDGET>, ()>
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static
{
    let (widget, component, relm) = create_widget::<WIDGET>(model_param);
    init_component::<WIDGET>(widget.stream(), component, &relm);
    Ok(widget)
}

/// 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, Update, Widget};
/// #
/// # struct Win {
/// #     window: Window,
/// # }
/// #
/// # impl Update for Win {
/// #     type Model = ();
/// #     type ModelParam = ();
/// #     type Msg = Msg;
/// #
/// #     fn model(_: &Relm<Self>, _: ()) -> () {
/// #         ()
/// #     }
/// #
/// #     fn update(&mut self, event: Msg) {
/// #     }
/// # }
/// #
/// # impl Widget for Win {
/// #     type Root = Window;
/// #
/// #     fn root(&self) -> Self::Root {
/// #         self.window.clone()
/// #     }
/// #
/// #     fn view(relm: &Relm<Self>, _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,
{
    gtk::init().map_err(|_| ())?;
    let _component = init::<WIDGET>(model_param)?;
    gtk::main();
    Ok(())
}

/// Emit the `msg` every `duration` ms.
pub fn interval<F: Fn() -> MSG + 'static, MSG: 'static>(stream: &EventStream<MSG>, duration: u32, constructor: F) {
    let stream = stream.clone();
    gtk::timeout_add(duration, move || {
        let msg = constructor();
        stream.emit(msg);
        Continue(true)
    });
}

/// After `duration` ms, emit `msg`.
pub fn timeout<F: Fn() -> MSG + 'static, MSG: 'static>(stream: &EventStream<MSG>, duration: u32, constructor: F) {
    let stream = stream.clone();
    gtk::timeout_add(duration, move || {
        let msg = constructor();
        stream.emit(msg);
        Continue(false)
    });
}
<commit_msg>Add missing gtk::init()<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+.
//!
//! This library provides a [`Widget`](trait.Widget.html) 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.3.0"
//! relm = "^0.11.0"
//! relm-derive = "^0.11.0"
//! ```
//!
//! More info can be found in the [readme](https://github.com/antoyo/relm#relm).

#![warn(
    missing_docs,
    trivial_casts,
    trivial_numeric_casts,
    unused_extern_crates,
    unused_import_braces,
    unused_qualifications,
)]

/*
 * TODO: maybe remove SimpleMsg.
 *
 * TODO: improve README so that examples can be copy/pasted.
 * TODO: add tests for relm-derive-state.
 *
 * FIXME: some relm widgets requires { and } (see the rusic music-player) while other do not.
 * FIXME: should not require to import WidgetExt because it calls show().
 * FIXME: cannot have relm event with tuple as a value like:
 * RelmWidget {
 *     RelmEvent((value1, value2)) => …
 * }
 * TODO: use pub(crate) instead of pub so that we're not bound to make the model and msg structs pub.
 *
 * TODO: add init() method to the Widget (or Update) trait as a shortcut for init::<Widget>()?
 *
 * TODO: alternative to tokio with a trait to get FD and add this FD to glib (perhaps using a
 * GSource).
 * For timers, add a connect_timeout!() macro or something.
 *
 * TODO: show a warning when a component is imediately destroyed.
 * FIXME: cannot add a trailing coma at the end of a initializer list.
 * TODO: switch from gtk::main() to MainLoop to avoid issues with nested loops.
 * TODO: prefix generated container name with _ to hide warnings.
 * TODO: remove the code generation related to using self in event handling.
 * TODO: remove the closure transformer code.
 *
 * TODO: move most of the examples in the tests/ directory.
 * 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: add a FAQ with the question related to getting an error when not importing the gtk traits.
 *
 * 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.
 */

extern crate cairo;
extern crate glib;
extern crate glib_sys;
extern crate gobject_sys;
extern crate gtk;
extern crate libc;
extern crate relm_core;
extern crate relm_state;

mod component;
mod container;
mod drawing;
mod macros;
mod widget;

#[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 gtk::Continue;
use libc::{c_char, c_uint};
#[doc(hidden)]
pub use relm_core::{Channel, EventStream};
pub use relm_state::{
    DisplayVariant,
    IntoOption,
    IntoPair,
    Relm,
    Update,
    UpdateNew,
    execute,
};
use relm_state::init_component;

pub use component::Component;
pub use container::{Container, ContainerComponent, ContainerWidget};
pub use drawing::DrawHandler;
pub use widget::{Widget, WidgetTest};

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 $(::relm::)*Widget for $self_type:ident { $($tts:tt)* }) => {
        pub use self::__relm_gen_private::$self_type;
    };
}

fn create_widget_test<WIDGET>(model_param: WIDGET::ModelParam) -> (Component<WIDGET>, WIDGET::Widgets)
    where WIDGET: Widget + WidgetTest + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    let (widget, component, relm): (_, WIDGET, _) = create_widget(model_param);
    let widgets = component.get_widgets();
    init_component::<WIDGET>(widget.stream(), component, &relm);
    (widget, widgets)
}

/// 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>(model_param: CHILDWIDGET::ModelParam)
        -> Component<CHILDWIDGET>
    where CHILDWIDGET: Widget + 'static,
          CHILDWIDGET::Msg: DisplayVariant + 'static,
{
    let (widget, component, child_relm) = create_widget::<CHILDWIDGET>(model_param);
    init_component::<CHILDWIDGET>(widget.stream(), component, &child_relm);
    widget
}

/// Create a new relm container 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_container<CHILDWIDGET>(model_param: CHILDWIDGET::ModelParam)
        -> ContainerComponent<CHILDWIDGET>
    where CHILDWIDGET: Container + Widget + 'static,
          CHILDWIDGET::Msg: DisplayVariant + 'static,
{
    let (widget, component, child_relm) = create_widget::<CHILDWIDGET>(model_param);
    let container = component.container().clone();
    let containers = component.other_containers();
    init_component::<CHILDWIDGET>(widget.stream(), component, &child_relm);
    ContainerComponent::new(widget, container, containers)
}

/// Create a new relm widget with `model_param` as initialization value.
fn create_widget<WIDGET>(model_param: WIDGET::ModelParam)
    -> (Component<WIDGET>, WIDGET, Relm<WIDGET>)
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    let stream = EventStream::new();

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

    let root = widget.root().clone();
    (Component::new(stream, root), widget, relm)
}

/// 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, Update, Widget, WidgetTest};
/// #
/// # #[derive(Clone)]
/// # struct Win {
/// #     window: Window,
/// # }
/// #
/// # impl Update for Win {
/// #     type Model = ();
/// #     type ModelParam = ();
/// #     type Msg = Msg;
/// #
/// #     fn model(_: &Relm<Self>, _: ()) -> () {
/// #         ()
/// #     }
/// #
/// #     fn update(&mut self, event: Msg) {
/// #     }
/// # }
/// #
/// # impl WidgetTest for Win {
/// #     type Widgets = Win;
/// #
/// #     fn get_widgets(&self) -> Self::Widgets {
/// #         self.clone()
/// #     }
/// # }
/// #
/// # impl Widget for Win {
/// #     type Root = Window;
/// #
/// #     fn root(&self) -> Self::Root {
/// #         self.window.clone()
/// #     }
/// #
/// #     fn view(relm: &Relm<Self>, _model: Self::Model) -> Self {
/// #         let window = Window::new(WindowType::Toplevel);
/// #
/// #         Win {
/// #             window: window,
/// #         }
/// #     }
/// # }
/// #
/// # #[derive(Msg)]
/// # enum Msg {}
/// # fn main() {
/// let (component, widgets) = relm::init_test::<Win>(()).unwrap();
/// # }
/// ```
pub fn init_test<WIDGET>(model_param: WIDGET::ModelParam) ->
    Result<(Component<WIDGET>, WIDGET::Widgets), ()>
    where WIDGET: Widget + WidgetTest + 'static,
          WIDGET::Msg: DisplayVariant + 'static,
{
    gtk::init().map_err(|_| ())?;
    let component = create_widget_test::<WIDGET>(model_param);
    Ok(component)
}

/// Initialize a widget.
pub fn init<WIDGET>(model_param: WIDGET::ModelParam) -> Result<Component<WIDGET>, ()>
    where WIDGET: Widget + 'static,
          WIDGET::Msg: DisplayVariant + 'static
{
    let (widget, component, relm) = create_widget::<WIDGET>(model_param);
    init_component::<WIDGET>(widget.stream(), component, &relm);
    Ok(widget)
}

/// 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, Update, Widget};
/// #
/// # struct Win {
/// #     window: Window,
/// # }
/// #
/// # impl Update for Win {
/// #     type Model = ();
/// #     type ModelParam = ();
/// #     type Msg = Msg;
/// #
/// #     fn model(_: &Relm<Self>, _: ()) -> () {
/// #         ()
/// #     }
/// #
/// #     fn update(&mut self, event: Msg) {
/// #     }
/// # }
/// #
/// # impl Widget for Win {
/// #     type Root = Window;
/// #
/// #     fn root(&self) -> Self::Root {
/// #         self.window.clone()
/// #     }
/// #
/// #     fn view(relm: &Relm<Self>, _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,
{
    gtk::init().map_err(|_| ())?;
    let _component = init::<WIDGET>(model_param)?;
    gtk::main();
    Ok(())
}

/// Emit the `msg` every `duration` ms.
pub fn interval<F: Fn() -> MSG + 'static, MSG: 'static>(stream: &EventStream<MSG>, duration: u32, constructor: F) {
    let stream = stream.clone();
    gtk::timeout_add(duration, move || {
        let msg = constructor();
        stream.emit(msg);
        Continue(true)
    });
}

/// After `duration` ms, emit `msg`.
pub fn timeout<F: Fn() -> MSG + 'static, MSG: 'static>(stream: &EventStream<MSG>, duration: u32, constructor: F) {
    let stream = stream.clone();
    gtk::timeout_add(duration, move || {
        let msg = constructor();
        stream.emit(msg);
        Continue(false)
    });
}
<|endoftext|>


<commit_before>//! Board Support Crate for the bluepill
//!
//! # Usage
//!
//! Follow `cortex-m-quickstart` [instructions][i] but remove the `memory.x`
//! linker script and the `build.rs` build script file as part of the
//! configuration of the quickstart crate. Additionally, uncomment the "if using
//! ITM" block in the `.gdbinit` file.
//!
//! [i]: https://docs.rs/cortex-m-quickstart/0.1.1/cortex_m_quickstart/
//!
//! # Examples
//!
//! Check the [examples] module.
//!
//! [examples]: ./examples/index.html

#![deny(missing_docs)]
//#![deny(warnings)]
#![no_std]
#![feature(associated_type_defaults)]

extern crate cast;
pub extern crate stm32f103xx;

// For documentation only
pub mod examples;

pub mod led;
//pub mod serial;
pub mod timer;
pub mod clock;
pub mod pin;

pub mod frequency;
<commit_msg>re-add hal crate<commit_after>//! Board Support Crate for the bluepill
//!
//! # Usage
//!
//! Follow `cortex-m-quickstart` [instructions][i] but remove the `memory.x`
//! linker script and the `build.rs` build script file as part of the
//! configuration of the quickstart crate. Additionally, uncomment the "if using
//! ITM" block in the `.gdbinit` file.
//!
//! [i]: https://docs.rs/cortex-m-quickstart/0.1.1/cortex_m_quickstart/
//!
//! # Examples
//!
//! Check the [examples] module.
//!
//! [examples]: ./examples/index.html

#![deny(missing_docs)]
//#![deny(warnings)]
#![no_std]
#![feature(associated_type_defaults)]

extern crate cast;
pub extern crate stm32f103xx;
extern crate hal;

// For documentation only
pub mod examples;

pub mod led;
//pub mod serial;
pub mod timer;
pub mod clock;
pub mod pin;

pub mod frequency;
<|endoftext|>


<commit_before>use std::fmt::{self, Debug, Formatter};

/// A data-structure for storing a sequence of 4-bit values.
///
/// Values are stored in a `Vec<u8>`, with two values per byte.
///
/// Values at even indices are stored in the most-significant half of their byte,
/// while values at odd indices are stored in the least-significant half.
///
/// Imagine a vector of MSB bytes, and you'll be right.
///
/// n = [_ _ | _ _ | _ _]
///
/// # Invariants
/// * If the length is odd, then the second half of the last byte must be 0.
pub struct NibbleVec {
    length: usize,
    data: Vec<u8>
}

impl NibbleVec {
    /// Create an empty nibble vector.
    pub fn new() -> NibbleVec {
        NibbleVec {
            length: 0,
            data: Vec::new()
        }
    }

    /// Create a nibble vector from a vector of bytes.
    ///
    /// Each byte is split into two 4-bit entries (MSB, LSB).
    pub fn from_byte_vec(vec: Vec<u8>) -> NibbleVec {
        let length = 2 * vec.len();
        NibbleVec {
            length: length,
            data: vec
        }
    }

    /// Get the number of elements stored in the vector.
    pub fn len(&self) -> usize {
        self.length
    }

    /// Fetch a single entry from the vector.
    ///
    /// Guaranteed to be a value in the interval [0, 15].
    ///
    /// **Panics** if `idx >= self.len()`.
    pub fn get(&self, idx: usize) -> u8 {
        if idx >= self.length {
            panic!("attempted access beyond vector end. len is {}, index is {}", self.length, idx);
        }
        let vec_idx = idx / 2;
        match idx % 2 {
            // If the index is even, take the first (most significant) half of the stored byte.
            0 => self.data[vec_idx] >> 4,
            // If the index is odd, take the second (least significant) half.
            _ => self.data[vec_idx] & 0x0F
        }
    }

    /// Add a single nibble to the vector.
    ///
    /// Only the 4 least-significant bits of the value are used.
    pub fn push(&mut self, val: u8) {
        if self.length % 2 == 0 {
            self.data.push(val << 4);
        } else {
            let vec_len = self.data.len();

            // Zero the second half of the last byte just to be safe.
            self.data[vec_len - 1] &= 0xF0;

            // Write the new value.
            self.data[vec_len - 1] |= val & 0x0F;
        }
        self.length += 1;
    }

    /// Split the vector into two parts.
    ///
    /// All elements at or following the given index are returned in a new `NibbleVec`,
    /// with exactly `idx` elements remaining in this vector.
    ///
    /// **Panics** if `idx > self.len()`.
    pub fn split(&mut self, idx: usize) -> NibbleVec {
        if idx > self.length {
            panic!("attempted to split past vector end. len is {}, index is {}", self.length, idx);
        } else if idx == self.length {
            NibbleVec::new()
        } else if idx % 2 == 0 {
            self.split_even(idx)
        } else {
            self.split_odd(idx)
        }
    }

    /// Split function for odd *indices*.
    #[inline(always)]
    fn split_odd(&mut self, idx: usize) -> NibbleVec {
        let tail_vec_size = (self.length - idx) / 2;
        let mut tail = NibbleVec::from_byte_vec(Vec::with_capacity(tail_vec_size));

        // Perform an overlap copy, copying the last nibble of the original vector only if
        // the length of the new tail is *odd*.
        let tail_length = self.length - idx;
        let take_last = tail_length % 2 == 1;
        self.overlap_copy(idx / 2, self.data.len(), &mut tail.data, &mut tail.length, take_last);

        // Remove the copied bytes, being careful to skip the idx byte.
        for _ in range(idx / 2 + 1, self.data.len()) {
            self.data.pop();
        }

        // Zero the second half of the index byte so as to maintain the last-nibble invariant.
        self.data[idx / 2] &= 0xF0;

        // Update the length of the first NibbleVec.
        self.length = idx;

        tail
    }

    /// Split function for even *indices*.
    #[inline(always)]
    fn split_even(&mut self, idx: usize) -> NibbleVec {
        // Avoid allocating a temporary vector by copying all the bytes in order, then popping them.
        let tail_vec_size = (self.length - idx) / 2;
        let mut tail = NibbleVec::from_byte_vec(Vec::with_capacity(tail_vec_size));

        // Copy the bytes.
        for i in range(idx / 2, self.data.len()) {
            tail.data.push(self.data[i]);
        }

        // Pop the same bytes.
        for _ in range(0, tail_vec_size) {
            self.data.pop();
        }

        // Update lengths.
        tail.length = self.length - idx;
        self.length = idx;

        tail
    }

    /// Copy data between the second half of self.data[start] and
    /// self.data[end - 1]. The second half of the last entry is included
    /// if include_last is true.
    #[inline(always)]
    fn overlap_copy(&self, start: usize, end: usize, vec: &mut Vec<u8>, length: &mut usize, include_last: bool) {
        // Copy up to the first half of the last byte.
        for i in range(start, end - 1) {
            // The first half is the second half of the old entry.
            let first_half = self.data[i] & 0x0f;

            // The second half is the first half of the next entry.
            let second_half = self.data[i + 1] >> 4;

            vec.push((first_half << 4) | second_half);
            *length += 2;
        }

        if include_last {
            let last = self.data[end - 1] & 0x0f;
            vec.push(last << 4);
            *length += 1;
        }
    }

    /// Append another nibble vector.
    pub fn join(&mut self, other: &NibbleVec) {
        // If the length is even, we can append directly.
        if self.length % 2 == 0 {
            self.length += other.length;
            self.data.push_all(other.data.as_slice());
            return;
        }

        // If the other vector is empty, bail out.
        if other.len() == 0 {
            return;
        }

        // If the length is odd, we have to perform an overlap copy.
        // Copy the first half of the first element, to make the vector an even length.
        self.push(other.get(0));

        // Copy the rest of the vector using an overlap copy.
        let take_last = other.len() % 2 == 0;
        other.overlap_copy(0, other.data.len(), &mut self.data, &mut self.length, take_last);
    }
}

impl PartialEq<[u8]> for NibbleVec {
    fn eq(&self, other: &[u8]) -> bool {
        if other.len() != self.len() {
            return false;
        }

        for (i, x) in other.iter().enumerate() {
            if self.get(i) != *x {
                return false;
            }
        }
        true
    }
}

impl Clone for NibbleVec {
    fn clone(&self) -> NibbleVec {
        NibbleVec {
            length: self.length,
            data: self.data.clone()
        }
    }
}

impl Debug for NibbleVec {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "NibbleVec ["));

        if self.len() > 0 {
            try!(write!(fmt, "{}", self.get(0)));
        }

        for i in range(1, self.len()) {
            try!(write!(fmt, ", {}", self.get(i)));
        }
        write!(fmt, "]")
    }
}

#[cfg(test)]
mod test {
    use NibbleVec;

    fn v8_7_6_5() -> NibbleVec {
        NibbleVec::from_byte_vec(vec![8 << 4 | 7, 6 << 4 | 5])
    }

    fn v11_10_9() -> NibbleVec {
        let mut result = NibbleVec::from_byte_vec(vec![11 << 4 | 10]);
        result.push(9);
        result
    }

    #[test]
    fn get() {
        let nv = NibbleVec::from_byte_vec(vec![3 << 4 | 7]);
        assert_eq!(nv.get(0), 3u8);
        assert_eq!(nv.get(1), 7u8);
    }

    #[test]
    fn push() {
        let mut nv = NibbleVec::new();
        let data = vec![0, 1, 3, 5, 7, 9, 11, 15];
        for val in data.iter() {
            nv.push(*val);
        }

        for (i, val) in data.iter().enumerate() {
            assert_eq!(nv.get(i), *val);
        }
    }

    fn split_test(  nibble_vec: &NibbleVec,
                    idx: usize,
                    first: Vec<u8>,
                    second: Vec<u8>) {
        let mut init = nibble_vec.clone();
        let tail = init.split(idx);
        assert!(init == first[]);
        assert!(tail == second[]);
    }

    #[test]
    fn split_even_length() {
        let even_length = v8_7_6_5();
        split_test(&even_length, 0, vec![], vec![8, 7, 6, 5]);
        split_test(&even_length, 1, vec![8], vec![7, 6, 5]);
        split_test(&even_length, 2, vec![8, 7], vec![6, 5]);
        split_test(&even_length, 4, vec![8, 7, 6, 5], vec![]);
    }

    #[test]
    fn split_odd_length() {
        let odd_length = v11_10_9();
        split_test(&odd_length, 0, vec![], vec![11, 10, 9]);
        split_test(&odd_length, 1, vec![11], vec![10, 9]);
        split_test(&odd_length, 2, vec![11, 10], vec![9]);
        split_test(&odd_length, 3, vec![11, 10, 9], vec![]);
    }

    /// Join vec2 onto vec1 and ensure that the results matches the one expected.
    fn join_test(vec1: &NibbleVec, vec2: &NibbleVec, result: Vec<u8>) {
        let mut joined = vec1.clone();
        joined.join(vec2);
        assert!(joined == result[]);
    }

    #[test]
    fn join_even_length() {
        let v1 = v8_7_6_5();
        let v2 = v11_10_9();
        join_test(&v1, &v2, vec![8, 7, 6, 5, 11, 10, 9]);
        join_test(&v1, &v1, vec![8, 7, 6, 5, 8, 7, 6, 5]);
        join_test(&v1, &NibbleVec::new(), vec![8, 7, 6, 5]);
        join_test(&NibbleVec::new(), &v1, vec![8, 7, 6, 5]);
    }

    #[test]
    fn join_odd_length() {
        let v1 = v8_7_6_5();
        let v2 = v11_10_9();
        join_test(&v2, &v1, vec![11, 10, 9, 8, 7, 6, 5]);
        join_test(&v2, &v2, vec![11, 10, 9, 11, 10, 9]);
        join_test(&v2, &NibbleVec::new(), vec![11, 10, 9]);
    }
}
<commit_msg>Add a test case for the memory re-use bug.<commit_after>use std::fmt::{self, Debug, Formatter};

/// A data-structure for storing a sequence of 4-bit values.
///
/// Values are stored in a `Vec<u8>`, with two values per byte.
///
/// Values at even indices are stored in the most-significant half of their byte,
/// while values at odd indices are stored in the least-significant half.
///
/// Imagine a vector of MSB bytes, and you'll be right.
///
/// n = [_ _ | _ _ | _ _]
///
/// # Invariants
/// * If the length is odd, then the second half of the last byte must be 0.
pub struct NibbleVec {
    length: usize,
    data: Vec<u8>
}

impl NibbleVec {
    /// Create an empty nibble vector.
    pub fn new() -> NibbleVec {
        NibbleVec {
            length: 0,
            data: Vec::new()
        }
    }

    /// Create a nibble vector from a vector of bytes.
    ///
    /// Each byte is split into two 4-bit entries (MSB, LSB).
    pub fn from_byte_vec(vec: Vec<u8>) -> NibbleVec {
        let length = 2 * vec.len();
        NibbleVec {
            length: length,
            data: vec
        }
    }

    /// Get the number of elements stored in the vector.
    pub fn len(&self) -> usize {
        self.length
    }

    /// Fetch a single entry from the vector.
    ///
    /// Guaranteed to be a value in the interval [0, 15].
    ///
    /// **Panics** if `idx >= self.len()`.
    pub fn get(&self, idx: usize) -> u8 {
        if idx >= self.length {
            panic!("attempted access beyond vector end. len is {}, index is {}", self.length, idx);
        }
        let vec_idx = idx / 2;
        match idx % 2 {
            // If the index is even, take the first (most significant) half of the stored byte.
            0 => self.data[vec_idx] >> 4,
            // If the index is odd, take the second (least significant) half.
            _ => self.data[vec_idx] & 0x0F
        }
    }

    /// Add a single nibble to the vector.
    ///
    /// Only the 4 least-significant bits of the value are used.
    pub fn push(&mut self, val: u8) {
        if self.length % 2 == 0 {
            self.data.push(val << 4);
        } else {
            let vec_len = self.data.len();

            // Zero the second half of the last byte just to be safe.
            self.data[vec_len - 1] &= 0xF0;

            // Write the new value.
            self.data[vec_len - 1] |= val & 0x0F;
        }
        self.length += 1;
    }

    /// Split the vector into two parts.
    ///
    /// All elements at or following the given index are returned in a new `NibbleVec`,
    /// with exactly `idx` elements remaining in this vector.
    ///
    /// **Panics** if `idx > self.len()`.
    pub fn split(&mut self, idx: usize) -> NibbleVec {
        if idx > self.length {
            panic!("attempted to split past vector end. len is {}, index is {}", self.length, idx);
        } else if idx == self.length {
            NibbleVec::new()
        } else if idx % 2 == 0 {
            self.split_even(idx)
        } else {
            self.split_odd(idx)
        }
    }

    /// Split function for odd *indices*.
    #[inline(always)]
    fn split_odd(&mut self, idx: usize) -> NibbleVec {
        let tail_vec_size = (self.length - idx) / 2;
        let mut tail = NibbleVec::from_byte_vec(Vec::with_capacity(tail_vec_size));

        // Perform an overlap copy, copying the last nibble of the original vector only if
        // the length of the new tail is *odd*.
        let tail_length = self.length - idx;
        let take_last = tail_length % 2 == 1;
        self.overlap_copy(idx / 2, self.data.len(), &mut tail.data, &mut tail.length, take_last);

        // Remove the copied bytes, being careful to skip the idx byte.
        for _ in range(idx / 2 + 1, self.data.len()) {
            self.data.pop();
        }

        // Zero the second half of the index byte so as to maintain the last-nibble invariant.
        self.data[idx / 2] &= 0xF0;

        // Update the length of the first NibbleVec.
        self.length = idx;

        tail
    }

    /// Split function for even *indices*.
    #[inline(always)]
    fn split_even(&mut self, idx: usize) -> NibbleVec {
        // Avoid allocating a temporary vector by copying all the bytes in order, then popping them.
        let tail_vec_size = (self.length - idx) / 2;
        let mut tail = NibbleVec::from_byte_vec(Vec::with_capacity(tail_vec_size));

        // Copy the bytes.
        for i in range(idx / 2, self.data.len()) {
            tail.data.push(self.data[i]);
        }

        // Pop the same bytes.
        for _ in range(0, tail_vec_size) {
            self.data.pop();
        }

        // Update lengths.
        tail.length = self.length - idx;
        self.length = idx;

        tail
    }

    /// Copy data between the second half of self.data[start] and
    /// self.data[end - 1]. The second half of the last entry is included
    /// if include_last is true.
    #[inline(always)]
    fn overlap_copy(&self, start: usize, end: usize, vec: &mut Vec<u8>, length: &mut usize, include_last: bool) {
        // Copy up to the first half of the last byte.
        for i in range(start, end - 1) {
            // The first half is the second half of the old entry.
            let first_half = self.data[i] & 0x0f;

            // The second half is the first half of the next entry.
            let second_half = self.data[i + 1] >> 4;

            vec.push((first_half << 4) | second_half);
            *length += 2;
        }

        if include_last {
            let last = self.data[end - 1] & 0x0f;
            vec.push(last << 4);
            *length += 1;
        }
    }

    /// Append another nibble vector.
    pub fn join(&mut self, other: &NibbleVec) {
        // If the length is even, we can append directly.
        if self.length % 2 == 0 {
            self.length += other.length;
            self.data.push_all(other.data.as_slice());
            return;
        }

        // If the other vector is empty, bail out.
        if other.len() == 0 {
            return;
        }

        // If the length is odd, we have to perform an overlap copy.
        // Copy the first half of the first element, to make the vector an even length.
        self.push(other.get(0));

        // Copy the rest of the vector using an overlap copy.
        let take_last = other.len() % 2 == 0;
        other.overlap_copy(0, other.data.len(), &mut self.data, &mut self.length, take_last);
    }
}

impl PartialEq<[u8]> for NibbleVec {
    fn eq(&self, other: &[u8]) -> bool {
        if other.len() != self.len() {
            return false;
        }

        for (i, x) in other.iter().enumerate() {
            if self.get(i) != *x {
                return false;
            }
        }
        true
    }
}

impl Clone for NibbleVec {
    fn clone(&self) -> NibbleVec {
        NibbleVec {
            length: self.length,
            data: self.data.clone()
        }
    }
}

impl Debug for NibbleVec {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "NibbleVec ["));

        if self.len() > 0 {
            try!(write!(fmt, "{}", self.get(0)));
        }

        for i in range(1, self.len()) {
            try!(write!(fmt, ", {}", self.get(i)));
        }
        write!(fmt, "]")
    }
}

#[cfg(test)]
mod test {
    use NibbleVec;

    fn v8_7_6_5() -> NibbleVec {
        NibbleVec::from_byte_vec(vec![8 << 4 | 7, 6 << 4 | 5])
    }

    fn v11_10_9() -> NibbleVec {
        let mut result = NibbleVec::from_byte_vec(vec![11 << 4 | 10]);
        result.push(9);
        result
    }

    #[test]
    fn get() {
        let nv = NibbleVec::from_byte_vec(vec![3 << 4 | 7]);
        assert_eq!(nv.get(0), 3u8);
        assert_eq!(nv.get(1), 7u8);
    }

    #[test]
    fn push() {
        let mut nv = NibbleVec::new();
        let data = vec![0, 1, 3, 5, 7, 9, 11, 15];
        for val in data.iter() {
            nv.push(*val);
        }

        for (i, val) in data.iter().enumerate() {
            assert_eq!(nv.get(i), *val);
        }
    }

    fn split_test(  nibble_vec: &NibbleVec,
                    idx: usize,
                    first: Vec<u8>,
                    second: Vec<u8>) {
        let mut init = nibble_vec.clone();
        let tail = init.split(idx);
        assert!(init == first[]);
        assert!(tail == second[]);
    }

    #[test]
    fn split_even_length() {
        let even_length = v8_7_6_5();
        split_test(&even_length, 0, vec![], vec![8, 7, 6, 5]);
        split_test(&even_length, 1, vec![8], vec![7, 6, 5]);
        split_test(&even_length, 2, vec![8, 7], vec![6, 5]);
        split_test(&even_length, 4, vec![8, 7, 6, 5], vec![]);
    }

    #[test]
    fn split_odd_length() {
        let odd_length = v11_10_9();
        split_test(&odd_length, 0, vec![], vec![11, 10, 9]);
        split_test(&odd_length, 1, vec![11], vec![10, 9]);
        split_test(&odd_length, 2, vec![11, 10], vec![9]);
        split_test(&odd_length, 3, vec![11, 10, 9], vec![]);
    }

    /// Join vec2 onto vec1 and ensure that the results matches the one expected.
    fn join_test(vec1: &NibbleVec, vec2: &NibbleVec, result: Vec<u8>) {
        let mut joined = vec1.clone();
        joined.join(vec2);
        assert!(joined == result[]);
    }

    #[test]
    fn join_even_length() {
        let v1 = v8_7_6_5();
        let v2 = v11_10_9();
        join_test(&v1, &v2, vec![8, 7, 6, 5, 11, 10, 9]);
        join_test(&v1, &v1, vec![8, 7, 6, 5, 8, 7, 6, 5]);
        join_test(&v1, &NibbleVec::new(), vec![8, 7, 6, 5]);
        join_test(&NibbleVec::new(), &v1, vec![8, 7, 6, 5]);
    }

    #[test]
    fn join_odd_length() {
        let v1 = v8_7_6_5();
        let v2 = v11_10_9();
        join_test(&v2, &v1, vec![11, 10, 9, 8, 7, 6, 5]);
        join_test(&v2, &v2, vec![11, 10, 9, 11, 10, 9]);
        join_test(&v2, &NibbleVec::new(), vec![11, 10, 9]);
    }

    /// Ensure that the last nibble is zeroed before reuse.
    #[test]
    fn memory_reuse() {
        let mut vec = NibbleVec::new();
        vec.push(10);
        vec.push(1);

        // Pushing.
        vec.split(1);
        vec.push(2);
        assert_eq!(vec.get(1), 2);

        // Joining.
        vec.split(1);
        vec.join(&NibbleVec::from_byte_vec(vec![1 << 4 | 3, 5 << 4]));
        assert_eq!(vec.get(1), 1);
    }
}
<|endoftext|>


<commit_before>//! Implements Forsyth–Edwards notation (FEN) parsing.

use regex::Regex;
use basetypes::*;

/// Represents a parse error.
pub struct ParseError;

/// Pieces placement desctiption.
pub struct PiecesPlacement {
    /// An array of occupation bitboards indexed by piece type.  For
    /// example, `piece_placement.piece_type[PAWN]` gives the set of
    /// all pawns on the board (white and black).
    pub piece_type: [Bitboard; 6],

    /// An array of occupation bitboards indexed by color.  For
    /// example, `piece_placement.color[WHITE]` gives the set of all
    /// white pieces and pawns on the board.
    pub color: [Bitboard; 2],
}

/// Parses a FEN string.
///
/// A FEN (Forsyth–Edwards Notation) string defines a particular
/// position using only the ASCII character set. A FEN string
/// contains six fields separated by a space. The fields are:
///
/// 1) Piece placement (from white's perspective). Each rank is
///    described, starting with rank 8 and ending with rank 1. Within
///    each rank, the contents of each square are described from file A
///    through file H. Following the Standard Algebraic Notation (SAN),
///    each piece is identified by a single letter taken from the
///    standard English names. White pieces are designated using
///    upper-case letters ("PNBRQK") whilst Black uses lowercase
///    ("pnbrqk"). Blank squares are noted using digits 1 through 8
///    (the number of blank squares), and "/" separates ranks.
///
/// 2) Active color. "w" means white moves next, "b" means black.
///
/// 3) Castling availability. If neither side can castle, this is
///    "-". Otherwise, this has one or more letters: "K" (White can
///    castle kingside), "Q" (White can castle queenside), "k" (Black
///    can castle kingside), and/or "q" (Black can castle queenside).
///
/// 4) En passant target square (in algebraic notation). If there's no
///    en passant target square, this is "-". If a pawn has just made a
///    2-square move, this is the position "behind" the pawn. This is
///    recorded regardless of whether there is a pawn in position to
///    make an en passant capture.
///
/// 5) Halfmove clock. This is the number of halfmoves since the last
///    pawn advance or capture. This is used to determine if a draw can
///    be claimed under the fifty-move rule.
///
/// 6) Fullmove number. The number of the full move. It starts at 1,
///    and is incremented after Black's move.
///
/// # Example:
/// The starting position: `rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w QKqk - 0 1`
pub fn parse_fen
    (s: &str)
     -> Result<(PiecesPlacement, Color, CastlingRights, Option<Square>, u8, u16), ParseError> {

    let fileds: Vec<_> = s.split_whitespace().collect();
    if fileds.len() == 6 {
        Ok((try!(parse_fen_piece_placement(fileds[0])),
            try!(parse_fen_active_color(fileds[1])),
            try!(parse_fen_castling_rights(fileds[2])),
            try!(parse_fen_enpassant_square(fileds[3])),
            try!(fileds[4].parse::<u8>().map_err(|_| ParseError)),
            match try!(fileds[5].parse::<u16>().map_err(|_| ParseError)) {
            x if x == 0 || x > 9000 => return Err(ParseError),
            x => x,
        }))
    } else {
        Err(ParseError)
    }
}

/// Parses a square in algebraic notation.
fn parse_square(s: &str) -> Result<Square, ParseError> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"^[a-h][1-8]$").unwrap();
    }

    if RE.is_match(s) {
        let mut chars = s.chars();
        let file = (chars.next().unwrap().to_digit(18).unwrap() - 10) as File;
        let rank = (chars.next().unwrap().to_digit(9).unwrap() - 1) as Rank;
        Ok(square(file, rank))
    } else {
        Err(ParseError)
    }
}

fn parse_fen_piece_placement(s: &str) -> Result<PiecesPlacement, ParseError> {

    // We start with an empty board. FEN describes the board
    // starting at A8 and going toward H1.
    let mut piece_type = [0u64; 6];
    let mut color = [0u64; 2];
    let mut file = 0;
    let mut rank = 7;

    // These are the possible productions in the grammar.
    enum Token {
        Piece(Color, PieceType),
        EmptySquares(u32),
        Separator,
    }

    for c in s.chars() {

        // Parse the next character.
        let token = match c {
            'K' => Token::Piece(WHITE, KING),
            'Q' => Token::Piece(WHITE, QUEEN),
            'R' => Token::Piece(WHITE, ROOK),
            'B' => Token::Piece(WHITE, BISHOP),
            'N' => Token::Piece(WHITE, KNIGHT),
            'P' => Token::Piece(WHITE, PAWN),
            'k' => Token::Piece(BLACK, KING),
            'q' => Token::Piece(BLACK, QUEEN),
            'r' => Token::Piece(BLACK, ROOK),
            'b' => Token::Piece(BLACK, BISHOP),
            'n' => Token::Piece(BLACK, KNIGHT),
            'p' => Token::Piece(BLACK, PAWN),
            n @ '1'...'8' => Token::EmptySquares(n.to_digit(9).unwrap()),
            '/' => Token::Separator,
            _ => return Err(ParseError),
        };

        // Update the board accordting to the token.
        match token {
            Token::Piece(_color, _piece) => {
                if file > 7 {
                    return Err(ParseError);
                }
                let mask = 1 << square(file, rank);
                piece_type[_piece] |= mask;
                color[_color] |= mask;
                file += 1;
            }
            Token::EmptySquares(n) => {
                file += n as File;
                if file > 8 {
                    return Err(ParseError);
                }
            }
            Token::Separator => {
                if file == 8 && rank > 0 {
                    file = 0;
                    rank -= 1;
                } else {
                    return Err(ParseError);
                }
            }
        }
    }

    // Ensure the piece placement field had the right length.
    if file == 8 && rank == 0 {
        Ok(PiecesPlacement {
            piece_type: piece_type,
            color: color,
        })
    } else {
        Err(ParseError)
    }
}

fn parse_fen_active_color(s: &str) -> Result<Color, ParseError> {
    match s {
        "w" => Ok(WHITE),
        "b" => Ok(BLACK),
        _ => Err(ParseError),
    }
}

fn parse_fen_castling_rights(s: &str) -> Result<CastlingRights, ParseError> {

    // We start with no caltling allowed.
    let mut rights = CastlingRights::new(0);

    // Then we parse the content and update the castling rights.
    if s != "-" {
        for c in s.chars() {
            match c {
                'K' => {
                    if rights.grant(WHITE, KINGSIDE) {
                        return Err(ParseError);
                    }
                }
                'Q' => {
                    if rights.grant(WHITE, QUEENSIDE) {
                        return Err(ParseError);
                    }
                }
                'k' => {
                    if rights.grant(BLACK, KINGSIDE) {
                        return Err(ParseError);
                    }
                }
                'q' => {
                    if rights.grant(BLACK, QUEENSIDE) {
                        return Err(ParseError);
                    }
                }
                _ => {
                    return Err(ParseError);
                }
            };
        }
    }

    // Successfully parsed.
    Ok(rights)
}

fn parse_fen_enpassant_square(s: &str) -> Result<Option<Square>, ParseError> {
    match s {
        "-" => Ok(None),
        _ => Ok(Some(try!(parse_square(s).map_err(|_| ParseError)))),
    }
}
<commit_msg>moved doc string<commit_after>//! Implements Forsyth–Edwards notation (FEN) parsing.
//!
//! A FEN (Forsyth–Edwards Notation) string defines a particular
//! position using only the ASCII character set. A FEN string
//! contains six fields separated by a space. The fields are:
//!
//! 1) Piece placement (from white's perspective). Each rank is
//!    described, starting with rank 8 and ending with rank 1. Within
//!    each rank, the contents of each square are described from file A
//!    through file H. Following the Standard Algebraic Notation (SAN),
//!    each piece is identified by a single letter taken from the
//!    standard English names. White pieces are designated using
//!    upper-case letters ("PNBRQK") whilst Black uses lowercase
//!    ("pnbrqk"). Blank squares are noted using digits 1 through 8
//!    (the number of blank squares), and "/" separates ranks.
//!
//! 2) Active color. "w" means white moves next, "b" means black.
//!
//! 3) Castling availability. If neither side can castle, this is
//!    "-". Otherwise, this has one or more letters: "K" (White can
//!    castle kingside), "Q" (White can castle queenside), "k" (Black
//!    can castle kingside), and/or "q" (Black can castle queenside).
//!
//! 4) En passant target square (in algebraic notation). If there's no
//!    en passant target square, this is "-". If a pawn has just made a
//!    2-square move, this is the position "behind" the pawn. This is
//!    recorded regardless of whether there is a pawn in position to
//!    make an en passant capture.
//!
//! 5) Halfmove clock. This is the number of halfmoves since the last
//!    pawn advance or capture. This is used to determine if a draw can
//!    be claimed under the fifty-move rule.
//!
//! 6) Fullmove number. The number of the full move. It starts at 1,
//!    and is incremented after Black's move.
//!
//! # Example:
//! The starting position: `rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w QKqk - 0 1`

use regex::Regex;
use basetypes::*;

/// Represents a parse error.
pub struct ParseError;

/// Pieces placement desctiption.
pub struct PiecesPlacement {
    /// An array of occupation bitboards indexed by piece type.  For
    /// example, `piece_placement.piece_type[PAWN]` gives the set of
    /// all pawns on the board (white and black).
    pub piece_type: [Bitboard; 6],

    /// An array of occupation bitboards indexed by color.  For
    /// example, `piece_placement.color[WHITE]` gives the set of all
    /// white pieces and pawns on the board.
    pub color: [Bitboard; 2],
}

/// Parses a FEN string.
pub fn parse_fen
    (s: &str)
     -> Result<(PiecesPlacement, Color, CastlingRights, Option<Square>, u8, u16), ParseError> {

    let fileds: Vec<_> = s.split_whitespace().collect();
    if fileds.len() == 6 {
        Ok((try!(parse_fen_piece_placement(fileds[0])),
            try!(parse_fen_active_color(fileds[1])),
            try!(parse_fen_castling_rights(fileds[2])),
            try!(parse_fen_enpassant_square(fileds[3])),
            try!(fileds[4].parse::<u8>().map_err(|_| ParseError)),
            match try!(fileds[5].parse::<u16>().map_err(|_| ParseError)) {
            x if x == 0 || x > 9000 => return Err(ParseError),
            x => x,
        }))
    } else {
        Err(ParseError)
    }
}

/// Parses a square in algebraic notation.
fn parse_square(s: &str) -> Result<Square, ParseError> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"^[a-h][1-8]$").unwrap();
    }

    if RE.is_match(s) {
        let mut chars = s.chars();
        let file = (chars.next().unwrap().to_digit(18).unwrap() - 10) as File;
        let rank = (chars.next().unwrap().to_digit(9).unwrap() - 1) as Rank;
        Ok(square(file, rank))
    } else {
        Err(ParseError)
    }
}

fn parse_fen_piece_placement(s: &str) -> Result<PiecesPlacement, ParseError> {

    // We start with an empty board. FEN describes the board
    // starting at A8 and going toward H1.
    let mut piece_type = [0u64; 6];
    let mut color = [0u64; 2];
    let mut file = 0;
    let mut rank = 7;

    // These are the possible productions in the grammar.
    enum Token {
        Piece(Color, PieceType),
        EmptySquares(u32),
        Separator,
    }

    for c in s.chars() {

        // Parse the next character.
        let token = match c {
            'K' => Token::Piece(WHITE, KING),
            'Q' => Token::Piece(WHITE, QUEEN),
            'R' => Token::Piece(WHITE, ROOK),
            'B' => Token::Piece(WHITE, BISHOP),
            'N' => Token::Piece(WHITE, KNIGHT),
            'P' => Token::Piece(WHITE, PAWN),
            'k' => Token::Piece(BLACK, KING),
            'q' => Token::Piece(BLACK, QUEEN),
            'r' => Token::Piece(BLACK, ROOK),
            'b' => Token::Piece(BLACK, BISHOP),
            'n' => Token::Piece(BLACK, KNIGHT),
            'p' => Token::Piece(BLACK, PAWN),
            n @ '1'...'8' => Token::EmptySquares(n.to_digit(9).unwrap()),
            '/' => Token::Separator,
            _ => return Err(ParseError),
        };

        // Update the board accordting to the token.
        match token {
            Token::Piece(_color, _piece) => {
                if file > 7 {
                    return Err(ParseError);
                }
                let mask = 1 << square(file, rank);
                piece_type[_piece] |= mask;
                color[_color] |= mask;
                file += 1;
            }
            Token::EmptySquares(n) => {
                file += n as File;
                if file > 8 {
                    return Err(ParseError);
                }
            }
            Token::Separator => {
                if file == 8 && rank > 0 {
                    file = 0;
                    rank -= 1;
                } else {
                    return Err(ParseError);
                }
            }
        }
    }

    // Ensure the piece placement field had the right length.
    if file == 8 && rank == 0 {
        Ok(PiecesPlacement {
            piece_type: piece_type,
            color: color,
        })
    } else {
        Err(ParseError)
    }
}

fn parse_fen_active_color(s: &str) -> Result<Color, ParseError> {
    match s {
        "w" => Ok(WHITE),
        "b" => Ok(BLACK),
        _ => Err(ParseError),
    }
}

fn parse_fen_castling_rights(s: &str) -> Result<CastlingRights, ParseError> {

    // We start with no caltling allowed.
    let mut rights = CastlingRights::new(0);

    // Then we parse the content and update the castling rights.
    if s != "-" {
        for c in s.chars() {
            match c {
                'K' => {
                    if rights.grant(WHITE, KINGSIDE) {
                        return Err(ParseError);
                    }
                }
                'Q' => {
                    if rights.grant(WHITE, QUEENSIDE) {
                        return Err(ParseError);
                    }
                }
                'k' => {
                    if rights.grant(BLACK, KINGSIDE) {
                        return Err(ParseError);
                    }
                }
                'q' => {
                    if rights.grant(BLACK, QUEENSIDE) {
                        return Err(ParseError);
                    }
                }
                _ => {
                    return Err(ParseError);
                }
            };
        }
    }

    // Successfully parsed.
    Ok(rights)
}

fn parse_fen_enpassant_square(s: &str) -> Result<Option<Square>, ParseError> {
    match s {
        "-" => Ok(None),
        _ => Ok(Some(try!(parse_square(s).map_err(|_| ParseError)))),
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::{Rand, Rng};
use rand::Closed01 as RandClosed01;

/// Encapsulates a floating point number in the range [0, 1] including both endpoints.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Closed01<F>(F);

impl Closed01<f32> {
    #[inline(always)]
    pub fn new(f: f32) -> Closed01<f32> {
        assert!(f >= 0.0 && f <= 1.0);
        Closed01(f)
    }

    #[inline(always)]
    pub fn zero() -> Closed01<f32> {
        Closed01(0.0)
    }

    #[inline(always)]
    pub fn middle() -> Closed01<f32> {
        Closed01(0.5)
    }

    #[inline(always)]
    pub fn one() -> Closed01<f32> {
        Closed01(1.0)
    }

    #[inline(always)]
    /// Returns the smaller of the two.
    pub fn min(self, other: Closed01<f32>) -> Closed01<f32> {
        if self.0 <= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the greater of the two.
    pub fn max(self, other: Closed01<f32>) -> Closed01<f32> {
        if self.0 >= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the distance between the two numbers.
    pub fn distance(self, other: Closed01<f32>) -> Closed01<f32> {
        let d = (self.0 - other.0).abs();
        debug_assert!(d >= 0.0 && d <= 1.0);
        Closed01(d)
    }

    #[inline(always)]
    pub fn get(self) -> f32 {
        debug_assert!(self.0 >= 0.0 && self.0 <= 1.0);
        self.0
    }

    #[inline(always)]
    /// The average of two values.
    pub fn avg(a: Closed01<f32>, b: Closed01<f32>) -> Closed01<f32> {
        let avg = (a.get() + b.get()) / 2.0;
        debug_assert!(avg >= 0.0 && avg <= 1.0);
        Closed01(avg)
    }

    #[inline(always)]
    /// Saturating add
    pub fn saturating_add(self, other: Closed01<f32>) -> Closed01<f32> {
        let mut sum = self.0 + other.0;
        if sum > 1.0 {
            sum = 1.0;
        }
        debug_assert!(sum >= 0.0 && sum <= 1.0);
        Closed01(sum)
    }

    #[inline(always)]
    /// Saturating sub
    pub fn saturating_sub(self, other: Closed01<f32>) -> Closed01<f32> {
        let mut sub = self.0 - other.0;
        if sub < 0.0 {
            sub = 0.0;
        }
        debug_assert!(sub >= 0.0 && sub <= 1.0);
        Closed01(sub)
    }

    #[inline(always)]
    /// Multiplies both numbers
    pub fn mul(self, scalar: Closed01<f32>) -> Closed01<f32> {
        let s = self.get() * scalar.get();
        debug_assert!(s >= 0.0 && s <= 1.0);
        Closed01(s)
    }

    #[inline(always)]
    pub fn approx_eq(self, other: Closed01<f32>, eps: Closed01<f32>) -> bool {
        self.distance(other) < eps
    }
}

impl Into<f32> for Closed01<f32> {
    fn into(self) -> f32 {
        self.get()
    }
}

impl Rand for Closed01<f32> {
    fn rand<R: Rng>(rng: &mut R) -> Closed01<f32> {
        Closed01::new(RandClosed01::<f32>::rand(rng).0)
    }
}

#[test]
fn test_into() {
    assert_eq!(0.5f32, Closed01::new(0.5).into());
}

#[test]
fn test_minmax() {
    let a = Closed01::new(0.4);
    let b = Closed01::new(0.5);
    assert_eq!(a, a.min(b));
    assert_eq!(a, b.min(a));
    assert_eq!(b, a.max(b));
    assert_eq!(b, b.max(a));
}

#[test]
fn test_saturation() {
    let a = Closed01::new(0.4);
    let b = Closed01::new(0.5);
    let c = Closed01::new(0.6);

    assert_eq!(0.9, a.saturating_add(b).get());
    assert_eq!(1.0, a.saturating_add(c).get());
    assert_eq!(1.0, b.saturating_add(c).get());

    assert_eq!(0.0, a.saturating_sub(b).get());
    assert_eq!(0.0, a.saturating_sub(c).get());
    assert_eq!(0.0, b.saturating_sub(c).get());

    let eps = Closed01::new(0.001);
    assert!(c.saturating_sub(b).approx_eq(Closed01::new(0.1), eps));
    assert!(c.saturating_sub(a).approx_eq(Closed01::new(0.2), eps));
}
<commit_msg>Add scale_up and scale_down<commit_after>extern crate rand;

use rand::{Rand, Rng};
use rand::Closed01 as RandClosed01;

/// Encapsulates a floating point number in the range [0, 1] including both endpoints.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Closed01<F>(F);

impl Closed01<f32> {
    #[inline(always)]
    pub fn new(f: f32) -> Closed01<f32> {
        assert!(f >= 0.0 && f <= 1.0);
        Closed01(f)
    }

    #[inline(always)]
    pub fn zero() -> Closed01<f32> {
        Closed01(0.0)
    }

    #[inline(always)]
    pub fn middle() -> Closed01<f32> {
        Closed01(0.5)
    }

    #[inline(always)]
    pub fn one() -> Closed01<f32> {
        Closed01(1.0)
    }

    #[inline(always)]
    /// Returns the smaller of the two.
    pub fn min(self, other: Closed01<f32>) -> Closed01<f32> {
        if self.0 <= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the greater of the two.
    pub fn max(self, other: Closed01<f32>) -> Closed01<f32> {
        if self.0 >= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the distance between the two numbers.
    pub fn distance(self, other: Closed01<f32>) -> Closed01<f32> {
        let d = (self.0 - other.0).abs();
        debug_assert!(d >= 0.0 && d <= 1.0);
        Closed01(d)
    }

    #[inline(always)]
    pub fn get(self) -> f32 {
        debug_assert!(self.0 >= 0.0 && self.0 <= 1.0);
        self.0
    }

    #[inline(always)]
    /// The average of two values.
    pub fn avg(a: Closed01<f32>, b: Closed01<f32>) -> Closed01<f32> {
        let avg = (a.get() + b.get()) / 2.0;
        debug_assert!(avg >= 0.0 && avg <= 1.0);
        Closed01(avg)
    }

    #[inline(always)]
    /// Saturating add
    pub fn saturating_add(self, other: Closed01<f32>) -> Closed01<f32> {
        let mut sum = self.0 + other.0;
        if sum > 1.0 {
            sum = 1.0;
        }
        debug_assert!(sum >= 0.0 && sum <= 1.0);
        Closed01(sum)
    }

    #[inline(always)]
    /// Saturating sub
    pub fn saturating_sub(self, other: Closed01<f32>) -> Closed01<f32> {
        let mut sub = self.0 - other.0;
        if sub < 0.0 {
            sub = 0.0;
        }
        debug_assert!(sub >= 0.0 && sub <= 1.0);
        Closed01(sub)
    }

    #[inline(always)]
    /// Multiplies both numbers
    pub fn mul(self, scalar: Closed01<f32>) -> Closed01<f32> {
        let s = self.get() * scalar.get();
        debug_assert!(s >= 0.0 && s <= 1.0);
        Closed01(s)
    }

    #[inline(always)]
    pub fn approx_eq(self, other: Closed01<f32>, eps: Closed01<f32>) -> bool {
        self.distance(other) < eps
    }

    #[inline(always)]
    /// This scales `self` towards 1.0
    pub fn scale_up(self, other: Closed01<f32>) -> Closed01<f32> {
        let s = self.0 + (1.0 - self.0) * other.0;
        debug_assert!(s >= 0.0 && s <= 1.0);
        Closed01(s)
    }

    #[inline(always)]
    /// This scales `self` towards 0.0
    pub fn scale_down(self, other: Closed01<f32>) -> Closed01<f32> {
        let s = self.0 - self.0 * other.0;
        debug_assert!(s >= 0.0 && s <= 1.0);
        Closed01(s)
    }
}

impl Into<f32> for Closed01<f32> {
    fn into(self) -> f32 {
        self.get()
    }
}

impl Rand for Closed01<f32> {
    fn rand<R: Rng>(rng: &mut R) -> Closed01<f32> {
        Closed01::new(RandClosed01::<f32>::rand(rng).0)
    }
}

#[test]
fn test_into() {
    assert_eq!(0.5f32, Closed01::new(0.5).into());
}

#[test]
fn test_minmax() {
    let a = Closed01::new(0.4);
    let b = Closed01::new(0.5);
    assert_eq!(a, a.min(b));
    assert_eq!(a, b.min(a));
    assert_eq!(b, a.max(b));
    assert_eq!(b, b.max(a));
}

#[test]
fn test_saturation() {
    let a = Closed01::new(0.4);
    let b = Closed01::new(0.5);
    let c = Closed01::new(0.6);

    assert_eq!(0.9, a.saturating_add(b).get());
    assert_eq!(1.0, a.saturating_add(c).get());
    assert_eq!(1.0, b.saturating_add(c).get());

    assert_eq!(0.0, a.saturating_sub(b).get());
    assert_eq!(0.0, a.saturating_sub(c).get());
    assert_eq!(0.0, b.saturating_sub(c).get());

    let eps = Closed01::new(0.001);
    assert!(c.saturating_sub(b).approx_eq(Closed01::new(0.1), eps));
    assert!(c.saturating_sub(a).approx_eq(Closed01::new(0.2), eps));
}

#[test]
fn test_scale_up() {
    let a = Closed01::new(0.0);
    let b = Closed01::new(1.0);
    let c = Closed01::new(0.5);

    assert_eq!(b, a.scale_up(b));
    assert_eq!(c, a.scale_up(c));

    assert_eq!(c, c.scale_up(a));
    assert_eq!(b, c.scale_up(b));
}

#[test]
fn test_scale_down() {
    let a = Closed01::new(0.0);
    let b = Closed01::new(1.0);
    let c = Closed01::new(0.5);

    assert_eq!(a, c.scale_down(b));
    assert_eq!(b, b.scale_down(a));
    assert_eq!(c, b.scale_down(c));
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

extern crate serde;
extern crate serde_json;
extern crate hyper;

pub mod requests;

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

    #[derive(Debug, Deserialize)]
    struct Args;

    #[derive(Debug, Deserialize)]
    struct Headers {
        #[serde(rename="Host")]
        host: String,
        #[serde(rename="User-Agent")]
        user_agent: String,
    }

    #[derive(Debug, Deserialize)]
    struct HttpBinData {
        // args: Args,
        headers: Headers,
        origin: String,
        url: String,
    }

    #[test]
    fn get() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::get(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
        let data: HttpBinData = res.from_json().unwrap();
        assert_eq!(data.url, URL);
        assert_eq!(data.headers.host, "httpbin.org");
        assert_eq!(data.headers.user_agent, concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
    }

    #[test]
    fn post() {
        const URL: &'static str = "http://httpbin.org/post";
        let res = requests::post(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn put() {
        const URL: &'static str = "http://httpbin.org/put";
        let res = requests::put(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn head() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::head(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn delete() {
        const URL: &'static str = "http://httpbin.org/delete";
        let res = requests::delete(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn user_agent() {
        let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                                env!("CARGO_PKG_VERSION"),
                                "\"\n}\n");
        const URL: &'static str = "http://httpbin.org/user-agent";
        let res = requests::get(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
        assert_eq!(res.text(), Some(useragent));
    }

    #[test]
    fn user_agent_json() {

        #[derive(Debug, Deserialize)]
        struct UserAgent {
            #[serde(rename="user-agent")]
            user_agent: String,
        }

        const URL: &'static str = "http://httpbin.org/user-agent";
        let res = requests::get(URL).unwrap();
        assert!(res.is_json());

        let ua: UserAgent = res.from_json().unwrap();
        assert_eq!(ua.user_agent, concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
    }
}
<commit_msg>Fix symbol export<commit_after>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

extern crate serde;
extern crate serde_json;
extern crate hyper;

pub mod requests;
pub use requests::{get, post, put, head, delete};

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

    #[derive(Debug, Deserialize)]
    struct Args;

    #[derive(Debug, Deserialize)]
    struct Headers {
        #[serde(rename="Host")]
        host: String,
        #[serde(rename="User-Agent")]
        user_agent: String,
    }

    #[derive(Debug, Deserialize)]
    struct HttpBinData {
        // args: Args,
        headers: Headers,
        origin: String,
        url: String,
    }

    #[test]
    fn simple_get() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = get(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
        let data: HttpBinData = res.from_json().unwrap();
        assert_eq!(data.url, URL);
        assert_eq!(data.headers.host, "httpbin.org");
        assert_eq!(data.headers.user_agent, concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
    }

    #[test]
    fn simple_post() {
        const URL: &'static str = "http://httpbin.org/post";
        let res = post(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn simple_put() {
        const URL: &'static str = "http://httpbin.org/put";
        let res = put(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn simple_head() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = head(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn simple_delete() {
        const URL: &'static str = "http://httpbin.org/delete";
        let res = delete(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn user_agent() {
        let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                                env!("CARGO_PKG_VERSION"),
                                "\"\n}\n");
        const URL: &'static str = "http://httpbin.org/user-agent";
        let res = requests::get(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), hyper::Ok);
        assert_eq!(res.reason(), "OK");
        assert_eq!(res.text(), Some(useragent));
    }

    #[test]
    fn user_agent_json() {

        #[derive(Debug, Deserialize)]
        struct UserAgent {
            #[serde(rename="user-agent")]
            user_agent: String,
        }

        const URL: &'static str = "http://httpbin.org/user-agent";
        let res = requests::get(URL).unwrap();
        assert!(res.is_json());

        let ua: UserAgent = res.from_json().unwrap();
        assert_eq!(ua.user_agent, concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
    }
}
<|endoftext|>


<commit_before>use std::option::Option;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

pub enum CellMetatype {
    tInt32
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

trait Metaformat<T> {
    fn construct(type_: CellMetatype, name: String) -> T;
}

pub struct CellFormat {
    name: String,
    type: CellMetatype
}

pub struct Cell {
    value: CellType
}

pub impl Metaformat<Cell> for Cell {
    fn construct(type_: CellMetatype, name: String) -> Cell {
        return match type {
            CellMetatype::tInt32 => Cell { value: CellType::Int32(None), name: name }
        }
    }
}

pub struct Row {
    cells: Vec<CellType>
}

pub struct Table {
    rows: Vec<Row>
}

trait ISet {
    fn size(&self) -> usize;
    fn add(&mut self, row: Row);
    fn remove(&mut self, index: usize); // FIXME
}
<commit_msg>Fix build<commit_after>use std::option::Option;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

pub enum CellMetatype {
    tInt32
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

trait Metaformat<T> {
    fn construct(type_: CellMetatype, name: String) -> T;
}

pub struct CellFormat {
    name: String,
    type_: CellMetatype
}

pub struct Cell {
    value: CellType
}

pub impl Metaformat<Cell> for Cell {
    fn construct(type_: CellMetatype, name: String) -> Cell {
        return match type {
            CellMetatype::tInt32 => Cell { value: CellType::Int32(None), name: name }
        }
    }
}

pub struct Row {
    cells: Vec<CellType>
}

pub struct Table {
    rows: Vec<Row>
}

trait ISet {
    fn size(&self) -> usize;
    fn add(&mut self, row: Row);
    fn remove(&mut self, index: usize); // FIXME
}
<|endoftext|>


<commit_before>#[no_mangle]
pub unsafe extern "C" fn memcpy(dest: *mut u8,
                                src: *const u8,
                                n: usize)
                                -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as isize) = *src.offset(i as isize);
        i += 1;
    }
    dest
}

#[no_mangle]
pub unsafe extern "C" fn memmove(dest: *mut u8,
                                 src: *const u8,
                                 n: usize)
                                 -> *mut u8 {
    if src < dest as *const u8 {
        // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as isize) = *src.offset(i as isize);
        }
    } else {
        // copy from beginning
        let mut i = 0;
        while i < n {
            *dest.offset(i as isize) = *src.offset(i as isize);
            i += 1;
        }
    }
    dest
}

#[no_mangle]
pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as isize) = c as u8;
        i += 1;
    }
    s
}

#[no_mangle]
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.offset(i as isize);
        let b = *s2.offset(i as isize);
        if a != b {
            return a as i32 - b as i32;
        }
        i += 1;
    }
    0
}
<commit_msg>Auto merge of #129 - pftbest:memset, r=japaric<commit_after>#[allow(warnings)]
#[cfg(target_pointer_width = "16")]
type c_int = i16;
#[allow(warnings)]
#[cfg(not(target_pointer_width = "16"))]
type c_int = i32;

#[no_mangle]
pub unsafe extern "C" fn memcpy(dest: *mut u8,
                                src: *const u8,
                                n: usize)
                                -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as isize) = *src.offset(i as isize);
        i += 1;
    }
    dest
}

#[no_mangle]
pub unsafe extern "C" fn memmove(dest: *mut u8,
                                 src: *const u8,
                                 n: usize)
                                 -> *mut u8 {
    if src < dest as *const u8 {
        // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as isize) = *src.offset(i as isize);
        }
    } else {
        // copy from beginning
        let mut i = 0;
        while i < n {
            *dest.offset(i as isize) = *src.offset(i as isize);
            i += 1;
        }
    }
    dest
}

#[no_mangle]
pub unsafe extern "C" fn memset(s: *mut u8, c: c_int, n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as isize) = c as u8;
        i += 1;
    }
    s
}

#[no_mangle]
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.offset(i as isize);
        let b = *s2.offset(i as isize);
        if a != b {
            return a as i32 - b as i32;
        }
        i += 1;
    }
    0
}
<|endoftext|>


<commit_before>use std::default::Default;
use libc::{c_int, c_char, uint8_t, uint32_t, int32_t};

pub static MAX_CPUID_LEVEL: uint = 32u;
pub static MAX_EXT_CPUID_LEVEL: uint = 32u;
pub static MAX_INTELFN4_LEVEL: uint = 4u;
pub static MAX_INTELFN11_LEVEL: uint = 4u;
pub static VENDOR_STR_MAX: uint = 16u;
pub static BRAND_STR_MAX: uint = 64u;
pub static CPU_FLAGS_MAX: uint = 128u;
pub static CPU_HINTS_MAX: uint = 16u;

#[repr(C)]
pub struct cpu_raw_data_t {
    pub basic_cpuid: [[uint32_t, ..MAX_CPUID_LEVEL], ..4u],
    pub ext_cpuid: [[uint32_t, ..MAX_EXT_CPUID_LEVEL], ..4u],
    pub intel_fn4: [[uint32_t, ..MAX_INTELFN4_LEVEL], ..4u],
    pub intel_fn11: [[uint32_t, ..MAX_INTELFN11_LEVEL], ..4u],
}

impl Default for cpu_raw_data_t {
    fn default() -> cpu_raw_data_t {
        cpu_raw_data_t {
            basic_cpuid: [[0, ..MAX_CPUID_LEVEL], ..4u],
            ext_cpuid: [[0, ..MAX_EXT_CPUID_LEVEL], ..4u],
            intel_fn4: [[0, ..MAX_INTELFN4_LEVEL], ..4u],
            intel_fn11: [[0, ..MAX_INTELFN11_LEVEL], ..4u],
        }
    }
}

#[repr(C)]
pub struct cpu_id_t {
    pub vendor_str: [c_char, ..VENDOR_STR_MAX],
    pub brand_str: [c_char, ..BRAND_STR_MAX],
    pub vendor: int32_t,
    pub flags: [uint8_t, ..CPU_FLAGS_MAX],
    pub family: int32_t,
    pub model: int32_t,
    pub stepping: int32_t,
    pub ext_family: int32_t,
    pub ext_model: int32_t,
    pub num_cores: int32_t,
    pub num_logical_cpus: int32_t,
    pub total_logical_cpus: int32_t,
    pub l1_data_cache: int32_t,
    pub l1_instruction_cache: int32_t,
    pub l2_cache: int32_t,
    pub l3_cache: int32_t,
    pub l1_assoc: int32_t,
    pub l2_assoc: int32_t,
    pub l3_assoc: int32_t,
    pub l1_cacheline: int32_t,
    pub l2_cacheline: int32_t,
    pub l3_cacheline: int32_t,
    pub cpu_codename: [c_char, ..64],
    pub sse_size: int32_t,
    pub detection_hints: [uint8_t, ..CPU_HINTS_MAX],
}

impl Default for cpu_id_t {
    fn default() -> cpu_id_t {
        cpu_id_t {
            vendor_str: [0, ..VENDOR_STR_MAX],
            brand_str: [0, ..BRAND_STR_MAX],
            vendor: 0,
            flags: [0u8, ..CPU_FLAGS_MAX],
            family: 0,
            model: 0,
            stepping: 0,
            ext_family: 0,
            ext_model: 0,
            num_cores: 0,
            num_logical_cpus: 0,
            total_logical_cpus: 0,
            l1_data_cache: 0,
            l1_instruction_cache: 0,
            l2_cache: 0,
            l3_cache: 0,
            l1_assoc: 0,
            l2_assoc: 0,
            l3_assoc: 0,
            l1_cacheline: 0,
            l2_cacheline: 0,
            l3_cacheline: 0,
            cpu_codename: [0, ..64],
            sse_size: 0,
            detection_hints: [0u8, ..CPU_HINTS_MAX],
        }
    }
}

#[link(name = "cpuid")]
extern {
    pub fn cpuid_present() -> c_int;
    pub fn cpuid_lib_version() -> *const c_char;
    pub fn cpuid_error() -> *const c_char;
    pub fn cpuid_get_raw_data(raw: *mut cpu_raw_data_t) -> c_int;
    pub fn cpu_identify(raw: *mut cpu_raw_data_t, data: *mut cpu_id_t) -> c_int;
    pub fn cpu_clock() -> c_int;
}
<commit_msg>Fixed transposed 2D arrays.<commit_after>use std::default::Default;
use libc::{c_int, c_char, uint8_t, uint32_t, int32_t};

pub static MAX_CPUID_LEVEL: uint = 32u;
pub static MAX_EXT_CPUID_LEVEL: uint = 32u;
pub static MAX_INTELFN4_LEVEL: uint = 4u;
pub static MAX_INTELFN11_LEVEL: uint = 4u;
pub static VENDOR_STR_MAX: uint = 16u;
pub static BRAND_STR_MAX: uint = 64u;
pub static CPU_FLAGS_MAX: uint = 128u;
pub static CPU_HINTS_MAX: uint = 16u;

#[repr(C)]
pub struct cpu_raw_data_t {
    pub basic_cpuid: [[uint32_t, ..4u], ..MAX_CPUID_LEVEL],
    pub ext_cpuid: [[uint32_t, ..4u], ..MAX_EXT_CPUID_LEVEL],
    pub intel_fn4: [[uint32_t, ..4u], ..MAX_INTELFN4_LEVEL],
    pub intel_fn11: [[uint32_t, ..4u], ..MAX_INTELFN11_LEVEL],
}

impl Default for cpu_raw_data_t {
    fn default() -> cpu_raw_data_t {
        cpu_raw_data_t {
            basic_cpuid: [[0, ..4u], ..MAX_CPUID_LEVEL],
            ext_cpuid: [[0, ..4u], ..MAX_EXT_CPUID_LEVEL],
            intel_fn4: [[0, ..4u], ..MAX_INTELFN4_LEVEL],
            intel_fn11: [[0, ..4u], ..MAX_INTELFN11_LEVEL],
        }
    }
}

#[repr(C)]
pub struct cpu_id_t {
    pub vendor_str: [c_char, ..VENDOR_STR_MAX],
    pub brand_str: [c_char, ..BRAND_STR_MAX],
    pub vendor: int32_t,
    pub flags: [uint8_t, ..CPU_FLAGS_MAX],
    pub family: int32_t,
    pub model: int32_t,
    pub stepping: int32_t,
    pub ext_family: int32_t,
    pub ext_model: int32_t,
    pub num_cores: int32_t,
    pub num_logical_cpus: int32_t,
    pub total_logical_cpus: int32_t,
    pub l1_data_cache: int32_t,
    pub l1_instruction_cache: int32_t,
    pub l2_cache: int32_t,
    pub l3_cache: int32_t,
    pub l1_assoc: int32_t,
    pub l2_assoc: int32_t,
    pub l3_assoc: int32_t,
    pub l1_cacheline: int32_t,
    pub l2_cacheline: int32_t,
    pub l3_cacheline: int32_t,
    pub cpu_codename: [c_char, ..64],
    pub sse_size: int32_t,
    pub detection_hints: [uint8_t, ..CPU_HINTS_MAX],
}

impl Default for cpu_id_t {
    fn default() -> cpu_id_t {
        cpu_id_t {
            vendor_str: [0, ..VENDOR_STR_MAX],
            brand_str: [0, ..BRAND_STR_MAX],
            vendor: 0,
            flags: [0u8, ..CPU_FLAGS_MAX],
            family: 0,
            model: 0,
            stepping: 0,
            ext_family: 0,
            ext_model: 0,
            num_cores: 0,
            num_logical_cpus: 0,
            total_logical_cpus: 0,
            l1_data_cache: 0,
            l1_instruction_cache: 0,
            l2_cache: 0,
            l3_cache: 0,
            l1_assoc: 0,
            l2_assoc: 0,
            l3_assoc: 0,
            l1_cacheline: 0,
            l2_cacheline: 0,
            l3_cacheline: 0,
            cpu_codename: [0, ..64],
            sse_size: 0,
            detection_hints: [0u8, ..CPU_HINTS_MAX],
        }
    }
}

#[link(name = "cpuid")]
extern {
    pub fn cpuid_present() -> c_int;
    pub fn cpuid_lib_version() -> *const c_char;
    pub fn cpuid_error() -> *const c_char;
    pub fn cpuid_get_raw_data(raw: *mut cpu_raw_data_t) -> c_int;
    pub fn cpu_identify(raw: *mut cpu_raw_data_t, data: *mut cpu_id_t) -> c_int;
    pub fn cpu_clock() -> c_int;
}
<|endoftext|>