<commit_before>extern crate euclid;

use std::mem;
use euclid::{Rect, Point2D, Size2D};

/// An immediate mode graphical user interface context.
///
/// The context persists over a frame and receives commands that combine GUI
/// description and input handling. At the end of the frame, the commands are
/// converted into rendering instructions for the GUI.
pub struct Context<T> {
    draw_list: Vec<DrawBatch<T>>,
    /// Texture value used for solid-color drawing
    solid_texture: T,

    // TODO: This is for demo purposes, need a proper layout state.
    layout_pos: Point2D<f32>,

    mouse_pos: Point2D<f32>,
    click_state: Option<ClickState>,
}

impl<T> Context<T>
    where T: Clone + PartialEq
{
    /// Construct a new interface context instance.
    ///
    /// The client must provide an initial texture instance that is used for
    /// drawing solid shapes. This can be a texture that consists of a single
    /// opaque white pixel.
    pub fn new(solid_texture: T) -> Context<T> {
        Context {
            draw_list: Vec::new(),
            solid_texture: solid_texture,

            layout_pos: Point2D::new(0.0, 0.0),

            mouse_pos: Point2D::new(0.0, 0.0),
            click_state: None,
        }
    }

    pub fn begin_frame(&mut self) {
        self.layout_pos = Point2D::new(10.0, 10.0);

        // Clean up transient mouse click info.
        if let Some(ClickState::Drag(_, _)) = self.click_state {
            self.click_state = None;
        }
        // TODO
    }

    pub fn text(&mut self, text: &str) {
        unimplemented!();
    }

    pub fn button(&mut self, caption: &str) -> bool {
        let area = Rect::new(self.layout_pos, Size2D::new(64.0, 16.0));
        self.layout_pos.y += 20.0;

        let hover = area.contains(&self.mouse_pos);
        let press = if let Some(ClickState::DragFrom(pos)) = self.click_state {
            area.contains(&pos) && area.contains(&self.mouse_pos)
        } else {
            false
        };

        self.fill_rect(area, [0.0, 0.0, 0.0, 1.0]);
        self.fill_rect(area.inflate(-1.0, -1.0),
                       if press {
                           [1.0, 1.0, 0.0, 1.0]
                       } else if hover {
                           [1.0, 0.5, 0.0, 1.0]
                       } else {
                           [1.0, 0.0, 0.0, 1.0]
                       });

        press
    }

    pub fn fill_rect(&mut self, area: Rect<f32>, color: [f32; 4]) {
        let (tl, tr, bl, br) = (area.origin,
                                area.top_right(),
                                area.bottom_left(),
                                area.bottom_right());
        self.start_solid_texture();

        let idx = self.draw_list.len() - 1;
        let batch = &mut self.draw_list[idx];
        let idx_offset = batch.vertices.len() as u16;

        batch.vertices.push(Vertex {
            pos: [tl.x, tl.y],
            color: color,
            tex: [0.0, 0.0],
        });
        batch.vertices.push(Vertex {
            pos: [tr.x, tr.y],
            color: color,
            tex: [0.0, 0.0],
        });
        batch.vertices.push(Vertex {
            pos: [br.x, br.y],
            color: color,
            tex: [0.0, 0.0],
        });
        batch.vertices.push(Vertex {
            pos: [bl.x, bl.y],
            color: color,
            tex: [0.0, 0.0],
        });

        batch.triangle_indices.push(idx_offset);
        batch.triangle_indices.push(idx_offset + 1);
        batch.triangle_indices.push(idx_offset + 2);

        batch.triangle_indices.push(idx_offset);
        batch.triangle_indices.push(idx_offset + 2);
        batch.triangle_indices.push(idx_offset + 3);
    }

    fn start_solid_texture(&mut self) {
        let tex = self.solid_texture.clone();
        self.start_texture(tex);
    }

    /// Ensure that there current draw batch has solid texture.
    fn start_texture(&mut self, texture: T) {
        // TODO: Actually have the solid texture value stashed somewhere.
        if self.draw_list.is_empty() ||
           self.draw_list[self.draw_list.len() - 1].texture != texture {
            self.draw_list.push(DrawBatch {
                texture: texture,
                clip: None,
                vertices: Vec::new(),
                triangle_indices: Vec::new(),
            });
        }
    }

    pub fn end_frame(&mut self) -> Vec<DrawBatch<T>> {
        let mut ret = Vec::new();
        mem::swap(&mut ret, &mut self.draw_list);
        ret
    }

    /// Register mouse button state.
    pub fn input_mouse_button(&mut self, id: MouseButton, is_down: bool) {
        if id == MouseButton::Left {
            if is_down {
                match self.click_state {
                    // We remember button being up, start dragging.
                    None => self.click_state = Some(ClickState::DragFrom(self.mouse_pos)),
                    // We remember a released click, someone is spamming lots
                    // of mouse stuff this frame? Just ignore the previous one
                    // then. (Maybe we should log the event spam somewhere?)
                    Some(ClickState::Drag(_, _)) => {
                        self.click_state = Some(ClickState::DragFrom(self.mouse_pos))
                    }
                    // Already dragging, do nothing. (Another weird state
                    // step, we should be getting multiple button-down events
                    // without a button-up in between to get here. Should log
                    // this one too if we had a log channel.)
                    Some(ClickState::DragFrom(_)) => {}
                }
            } else {
                match self.click_state {
                    // Dragging becomes a click when the mouse is released.
                    // The actual cleanup is done later.
                    //
                    // TODO: We could separate drag and click by mouse
                    // distance?
                    Some(ClickState::DragFrom(pos)) => {
                        self.click_state = Some(ClickState::Drag(pos, self.mouse_pos))
                    }
                    _ => {}
                }
            }
        }
        // TODO handle other buttons
    }

    /// Register mouse motion.
    pub fn input_mouse_move(&mut self, x: i32, y: i32) {
        self.mouse_pos = Point2D::new(x as f32, y as f32);
    }

    /// Register printable character input.
    pub fn input_char(&mut self, c: char) {
        // TODO
    }

    /// Register a nonprintable key state.
    pub fn input_key_state(&mut self, k: Keycode, is_down: bool) {
        // TODO
    }

    /// Build a font atlas from a TTF and construct a texture object.
    ///
    /// TODO: Font customization, point size, character ranges.
    pub fn init_font<F>(&mut self, ttf_data: &[u8], register_texture: F) -> Result<Font, ()>
        where F: FnOnce(&[u8], u32, u32) -> T
    {
        unimplemented!();
    }
}

/// A sequence of primitive draw operarations.
pub struct DrawBatch<T> {
    /// Texture used for the current batch, details depend on backend
    /// implementation
    pub texture: T,
    /// Clipping rectangle for the current batch
    pub clip: Option<Rect<f32>>,
    /// Vertex data
    pub vertices: Vec<Vertex>,
    /// Indices into the vertex array for the triangles that make up the batch
    pub triangle_indices: Vec<u16>,
}

#[derive(Copy, Clone)]
pub struct Vertex {
    pub pos: [f32; 2],
    pub color: [f32; 4],
    pub tex: [f32; 2],
}

/// Text alignment.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Align {
    Left,
    Center,
    Right,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum MouseButton {
    Left,
    Middle,
    Right,
}

#[derive(Copy, Clone, PartialEq, Debug)]
enum ClickState {
    /// Mouse was pressed down at pos and is still down.
    DragFrom(Point2D<f32>),
    /// Mouse was pressed down at pos, was subsequently released at pos2.
    Drag(Point2D<f32>, Point2D<f32>),
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Keycode {
    Tab,
    Shift,
    Ctrl,
    Enter,
    Backspace,
    Del,
    Up,
    Down,
    Left,
    Right,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Font(u64);
<commit_msg>Button click logic like it should be<commit_after>extern crate euclid;

use std::mem;
use euclid::{Rect, Point2D, Size2D};

/// An immediate mode graphical user interface context.
///
/// The context persists over a frame and receives commands that combine GUI
/// description and input handling. At the end of the frame, the commands are
/// converted into rendering instructions for the GUI.
pub struct Context<T> {
    draw_list: Vec<DrawBatch<T>>,
    /// Texture value used for solid-color drawing
    solid_texture: T,

    // TODO: This is for demo purposes, need a proper layout state.
    layout_pos: Point2D<f32>,

    mouse_pos: Point2D<f32>,
    click_state: ClickState,
}

impl<T> Context<T>
    where T: Clone + PartialEq
{
    /// Construct a new interface context instance.
    ///
    /// The client must provide an initial texture instance that is used for
    /// drawing solid shapes. This can be a texture that consists of a single
    /// opaque white pixel.
    pub fn new(solid_texture: T) -> Context<T> {
        Context {
            draw_list: Vec::new(),
            solid_texture: solid_texture,

            layout_pos: Point2D::new(0.0, 0.0),

            mouse_pos: Point2D::new(0.0, 0.0),
            click_state: ClickState::Unpressed,
        }
    }

    pub fn begin_frame(&mut self) {
        self.layout_pos = Point2D::new(10.0, 10.0);

        // TODO
    }

    pub fn text(&mut self, text: &str) {
        unimplemented!();
    }

    pub fn button(&mut self, caption: &str) -> bool {
        let area = Rect::new(self.layout_pos, Size2D::new(64.0, 16.0));
        self.layout_pos.y += 20.0;

        let hover = area.contains(&self.mouse_pos);
        let press = self.click_state.is_pressed() && area.contains(&self.mouse_pos);

        self.fill_rect(area, [0.0, 0.0, 0.0, 1.0]);
        self.fill_rect(area.inflate(-1.0, -1.0),
                       if press {
                           [1.0, 1.0, 0.0, 1.0]
                       } else if hover {
                           [1.0, 0.5, 0.0, 1.0]
                       } else {
                           [1.0, 0.0, 0.0, 1.0]
                       });

        press && self.click_state.is_release()
    }

    pub fn fill_rect(&mut self, area: Rect<f32>, color: [f32; 4]) {
        let (tl, tr, bl, br) = (area.origin,
                                area.top_right(),
                                area.bottom_left(),
                                area.bottom_right());
        self.start_solid_texture();

        let idx = self.draw_list.len() - 1;
        let batch = &mut self.draw_list[idx];
        let idx_offset = batch.vertices.len() as u16;

        batch.vertices.push(Vertex {
            pos: [tl.x, tl.y],
            color: color,
            tex: [0.0, 0.0],
        });
        batch.vertices.push(Vertex {
            pos: [tr.x, tr.y],
            color: color,
            tex: [0.0, 0.0],
        });
        batch.vertices.push(Vertex {
            pos: [br.x, br.y],
            color: color,
            tex: [0.0, 0.0],
        });
        batch.vertices.push(Vertex {
            pos: [bl.x, bl.y],
            color: color,
            tex: [0.0, 0.0],
        });

        batch.triangle_indices.push(idx_offset);
        batch.triangle_indices.push(idx_offset + 1);
        batch.triangle_indices.push(idx_offset + 2);

        batch.triangle_indices.push(idx_offset);
        batch.triangle_indices.push(idx_offset + 2);
        batch.triangle_indices.push(idx_offset + 3);
    }

    fn start_solid_texture(&mut self) {
        let tex = self.solid_texture.clone();
        self.start_texture(tex);
    }

    /// Ensure that there current draw batch has solid texture.
    fn start_texture(&mut self, texture: T) {
        // TODO: Actually have the solid texture value stashed somewhere.
        if self.draw_list.is_empty() ||
           self.draw_list[self.draw_list.len() - 1].texture != texture {
            self.draw_list.push(DrawBatch {
                texture: texture,
                clip: None,
                vertices: Vec::new(),
                triangle_indices: Vec::new(),
            });
        }
    }

    pub fn end_frame(&mut self) -> Vec<DrawBatch<T>> {
        // Clean up transient mouse click info.
        self.click_state = self.click_state.tick();

        let mut ret = Vec::new();
        mem::swap(&mut ret, &mut self.draw_list);
        ret
    }

    /// Register mouse button state.
    pub fn input_mouse_button(&mut self, id: MouseButton, is_down: bool) {
        if id == MouseButton::Left {
            if is_down {
                self.click_state = self.click_state.input_press(self.mouse_pos);
            } else {
                self.click_state = self.click_state.input_release(self.mouse_pos);
            }
        }
        // TODO handle other buttons
    }

    /// Register mouse motion.
    pub fn input_mouse_move(&mut self, x: i32, y: i32) {
        self.mouse_pos = Point2D::new(x as f32, y as f32);
    }

    /// Register printable character input.
    pub fn input_char(&mut self, c: char) {
        // TODO
    }

    /// Register a nonprintable key state.
    pub fn input_key_state(&mut self, k: Keycode, is_down: bool) {
        // TODO
    }

    /// Build a font atlas from a TTF and construct a texture object.
    ///
    /// TODO: Font customization, point size, character ranges.
    pub fn init_font<F>(&mut self, ttf_data: &[u8], register_texture: F) -> Result<Font, ()>
        where F: FnOnce(&[u8], u32, u32) -> T
    {
        unimplemented!();
    }
}

/// A sequence of primitive draw operarations.
pub struct DrawBatch<T> {
    /// Texture used for the current batch, details depend on backend
    /// implementation
    pub texture: T,
    /// Clipping rectangle for the current batch
    pub clip: Option<Rect<f32>>,
    /// Vertex data
    pub vertices: Vec<Vertex>,
    /// Indices into the vertex array for the triangles that make up the batch
    pub triangle_indices: Vec<u16>,
}

#[derive(Copy, Clone)]
pub struct Vertex {
    pub pos: [f32; 2],
    pub color: [f32; 4],
    pub tex: [f32; 2],
}

/// Text alignment.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Align {
    Left,
    Center,
    Right,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum MouseButton {
    Left,
    Middle,
    Right,
}

#[derive(Copy, Clone, PartialEq, Debug)]
enum ClickState {
    Unpressed,
    Press(Point2D<f32>),
    Drag(Point2D<f32>),
    Release(Point2D<f32>, Point2D<f32>),
}

impl ClickState {
    fn tick(self) -> ClickState {
        match self {
            ClickState::Unpressed => ClickState::Unpressed,
            ClickState::Press(p) => ClickState::Drag(p),
            ClickState::Drag(p) => ClickState::Drag(p),
            ClickState::Release(_, _) => ClickState::Unpressed
        }
    }

    fn input_press(self, pos: Point2D<f32>) -> ClickState {
        match self {
            ClickState::Unpressed => ClickState::Press(pos),
            ClickState::Press(p) => ClickState::Drag(p),
            ClickState::Drag(p) => ClickState::Drag(p),
            ClickState::Release(_, _) => ClickState::Press(pos),
        }
    }

    fn input_release(self, pos: Point2D<f32>) -> ClickState {
        match self {
            ClickState::Unpressed => ClickState::Unpressed,
            ClickState::Press(p) => ClickState::Release(p, pos),
            ClickState::Drag(p) => ClickState::Release(p, pos),
            ClickState::Release(p, _) => ClickState::Release(p, pos),
        }
    }

    fn is_pressed(&self) -> bool {
        match *self {
            ClickState::Press(_) | ClickState::Drag(_) | ClickState::Release(_, _) => true,
            ClickState::Unpressed => false
        }
    }

    fn is_release(&self) -> bool {
        if let ClickState::Release(_, _) = *self {
            true
        } else {
            false
        }
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Keycode {
    Tab,
    Shift,
    Ctrl,
    Enter,
    Backspace,
    Del,
    Up,
    Down,
    Left,
    Right,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Font(u64);
<|endoftext|>


<commit_before>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

extern crate libc;

extern crate glib_sys as glib_ffi;
extern crate gdk_sys as gdk_ffi;
extern crate gtk_sys as ffi;
extern crate cairo_sys as cairo_ffi;
#[macro_use]
extern crate glib;
extern crate gdk;
extern crate gdk_pixbuf;
extern crate cairo;
extern crate pango;

pub use glib::{
    Cast,
    Continue,
    Error,
    IsA,
    Object,
    StaticType,
    ToValue,
    Type,
    TypedValue,
    Value,
};

pub use ffi::GtkAccelFlags as AccelFlags;
pub use ffi::GtkAlign as Align;
pub use ffi::GtkArrowPlacement as ArrowPlacement;
pub use ffi::GtkArrowType as ArrowType;
pub use ffi::GtkAttachOptions as AttachOptions;
pub use ffi::GtkBaselinePosition as BaselinePosition;
pub use ffi::GtkBorderStyle as BorderStyle;
pub use ffi::GtkBuilderError as BuilderError;
pub use ffi::GtkButtonBoxStyle as ButtonBoxStyle;
pub use ffi::GtkButtonsType as ButtonsType;
pub use ffi::GtkCalendarDisplayOptions as CalendarDisplayOptions;
pub use ffi::GtkCellRendererState as CellRendererState;
pub use ffi::GtkCornerType as CornerType;
pub use ffi::GtkDeleteType as DeleteType;
pub use ffi::GtkDestDefaults as DestDefaults;
pub use ffi::GtkDialogFlags as DialogFlags;
pub use ffi::GtkDirectionType as DirectionType;
pub use ffi::GtkDragResult as DragResult;
pub use ffi::GtkEntryIconPosition as EntryIconPosition;
pub use ffi::GtkEventSequenceState as EventSequenceState;
pub use ffi::GtkExpanderStyle as ExpanderStyle;
pub use ffi::GtkFileChooserAction as FileChooserAction;
pub use ffi::GtkFileFilterFlags as FileFilterFlags;
pub use ffi::GtkIMPreeditStyle as IMPreeditStyle;
pub use ffi::GtkIMStatusStyle as IMStatusStyle;
pub use ffi::GtkIconSize as IconSize;
pub use ffi::GtkIconViewDropPosition as IconViewDropPosition;
pub use ffi::GtkImageType as ImageType;
pub use ffi::GtkInputHints as InputHints;
pub use ffi::GtkInputPurpose as InputPurpose;
pub use ffi::GtkJunctionSides as JunctionSides;
pub use ffi::GtkJustification as Justification;
pub use ffi::GtkLevelBarMode as LevelBarMode;
pub use ffi::GtkLicense as License;
pub use ffi::GtkMessageType as MessageType;
pub use ffi::GtkMovementStep as MovementStep;
pub use ffi::GtkNumberUpLayout as NumberUpLayout;
pub use ffi::GtkOrientation as Orientation;
pub use ffi::GtkPackType as PackType;
pub use ffi::GtkPageOrientation as PageOrientation;
pub use ffi::GtkPageSet as PageSet;
pub use ffi::GtkPathPriorityType as PathPriorityType;
pub use ffi::GtkPathType as PathType;
pub use ffi::GtkPlacesOpenFlags as PlacesOpenFlags;
pub use ffi::GtkPolicyType as PolicyType;
pub use ffi::GtkPositionType as PositionType;
pub use ffi::GtkPrintDuplex as PrintDuplex;
pub use ffi::GtkPrintPages as PrintPages;
pub use ffi::GtkPrintQuality as PrintQuality;
pub use ffi::GtkPropagationPhase as PropagationPhase;
pub use ffi::GtkRecentFilterFlags as RecentFilterFlags;
pub use ffi::GtkRecentSortType as RecentSortType;
pub use ffi::GtkRegionFlags as RegionFlags;
pub use ffi::GtkReliefStyle as ReliefStyle;
pub use ffi::GtkResizeMode as ResizeMode;
pub use ffi::GtkResponseType as ResponseType;
pub use ffi::GtkRevealerTransitionType as RevealerTransitionType;
pub use ffi::GtkScrollStep as ScrollStep;
pub use ffi::GtkScrollType as ScrollType;
pub use ffi::GtkScrollablePolicy as ScrollablePolicy;
pub use ffi::GtkSelectionMode as SelectionMode;
pub use ffi::GtkSensitivityType as SensitivityType;
pub use ffi::GtkShadowType as ShadowType;
pub use ffi::GtkSizeGroupMode as SizeGroupMode;
pub use ffi::GtkSizeRequestMode as SizeRequestMode;
pub use ffi::GtkSortType as SortType;
pub use ffi::GtkSpinButtonUpdatePolicy as SpinButtonUpdatePolicy;
pub use ffi::GtkSpinType as SpinType;
pub use ffi::GtkStackTransitionType as StackTransitionType;
pub use ffi::GtkStateFlags as StateFlags;
pub use ffi::GtkStateType as StateType;
pub use ffi::GtkTextDirection as TextDirection;
pub use ffi::GtkTextSearchFlags as TextSearchFlags;
pub use ffi::GtkTextWindowType as TextWindowType;
pub use ffi::GtkToolPaletteDragTargets as ToolPaletteDragTargets;
pub use ffi::GtkToolbarStyle as ToolbarStyle;
pub use ffi::GtkTreeModelFlags as TreeModelFlags;
pub use ffi::GtkTreeViewColumnSizing as TreeViewColumnSizing;
pub use ffi::GtkTreeViewDropPosition as TreeViewDropPosition;
pub use ffi::GtkTreeViewGridLines as TreeViewGridLines;
pub use ffi::GtkUnit as Unit;
pub use ffi::GtkWidgetHelpType as WidgetHelpType;
pub use ffi::GtkWindowPosition as WindowPosition;
pub use ffi::GtkWindowType as WindowType;
pub use ffi::GtkWrapMode as WrapMode;

pub const DIALOG_MODAL: DialogFlags = ffi::GTK_DIALOG_MODAL;

pub const STYLE_PROVIDER_PRIORITY_FALLBACK: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_FALLBACK;
pub const STYLE_PROVIDER_PRIORITY_THEME: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_THEME;
pub const STYLE_PROVIDER_PRIORITY_SETTINGS: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_SETTINGS;
pub const STYLE_PROVIDER_PRIORITY_APPLICATION: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_APPLICATION;
pub const STYLE_PROVIDER_PRIORITY_USER: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_USER;

#[macro_use]
mod rt;

mod auto;

mod app_chooser;
mod builder;
mod color_button;
mod color_chooser;
mod dialog;
mod entry_buffer;
mod file_chooser_dialog;
mod list_store;
mod message_dialog;
mod notebook;
mod recent_chooser_dialog;
mod recent_data;
mod recent_info;
mod rectangle;
mod requisition;
mod signal;
#[cfg(target_os = "linux")]
mod socket;
mod text_attributes;
mod text_buffer;
mod text_iter;
mod text_view;
mod tree_model;
mod tree_path;
mod tree_store;
mod tree_view;
mod widget;

pub mod prelude;

pub use auto::*;
pub use rt::*;
pub use signal::*;

pub use rectangle::Rectangle as Allocation;
pub use app_chooser::AppChooser;
pub use builder::{Builder, Buildable};
pub use color_chooser::ColorChooser;
pub use entry_buffer::EntryBuffer;
pub use recent_data::RecentData;
pub use recent_info::RecentInfo;
pub use rectangle::Rectangle;
pub use requisition::Requisition;
#[cfg(target_os = "linux")]
pub use socket::Socket;
pub use text_attributes::TextAttributes;
<commit_msg>Add some documentation<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # GTK+ 3 bindings
//!
//! This library contains safe Rust bindings for [GTK+ 3](http://www.gtk.org), a
//! multi-platform GUI toolkit. It's a part of [Gtk-rs](http://gtk-rs.org/).
//!
//! The library is a work in progress: expect missing bindings and breaking
//! changes. A steadily increasing share of the code is machine-generated from
//! GObject introspection metadata. The API docs were converted from the
//! upstream ones so until they've all been reviewed there will be incongruities
//! with actual Rust APIs.
//!
//! See also:
//!
//! - [Gtk-rs documentation overview](http://gtk-rs.org/docs/)
//!
//! - [General GLib family types and object system overview](../glib/index.html)
//!
//! - [GTK+ documentation](http://www.gtk.org/documentation.php)
//!
//! # Hello World
//!
//! ```no_run
//! extern crate gtk;
//! use gtk::prelude::*;
//! use gtk::{ButtonsType, DialogFlags, MessageType, MessageDialog, Window};
//!
//! fn main() {
//!     if gtk::init().is_err() {
//!         println!("Failed to initialize GTK.");
//!         return;
//!     }
//!     MessageDialog::new(None::<&Window>,
//!                        DialogFlags::empty(),
//!                        MessageType::Info,
//!                        ButtonsType::Ok,
//!                        "Hello World")
//!         .run();
//! }
//! ```
//!
//! # Crate features
//!
//! ## Library versions
//!
//! By default this crate provides only GTK+ 3.4 APIs. You can access more
//! modern APIs by selecting one of the following features: `3.6`, `3.8`,
//! `3.10`, `3.12`, `3.14`, `3.16`.
//!
//! `Cargo.toml` example:
//!
//! ```toml
//! [dependencies.gtk]
//! version = "0.x.y"
//! features = ["3.16"]
//! ```
//!
//! **Take care when choosing the version to target: some of your users might
//! not have easy access to the latest ones.** The higher the version, the fewer
//! users will have it installed.
//!
//! ## Lgpl-docs
//!
//! The Gtk-rs crates come with API docs missing because of licensing
//! incompatibilty. You can embed those docs locally via the `embed-lgpl-docs`
//! feature, e.g.
//!
//! ```shell
//! > cargo doc --features embed-lgpl-docs
//! ```
//!
//! Its counterpart `purge-lgpl-docs` removes those docs regardless of edits.
//!
//! These features **rewrite the crate sources** so it's sufficient to enable
//! them once. **Omitting them in the following cargo invocations will not undo
//! their effects!**

extern crate libc;

extern crate glib_sys as glib_ffi;
extern crate gdk_sys as gdk_ffi;
extern crate gtk_sys as ffi;
extern crate cairo_sys as cairo_ffi;
#[macro_use]
extern crate glib;
extern crate gdk;
extern crate gdk_pixbuf;
extern crate cairo;
extern crate pango;

pub use glib::{
    Cast,
    Continue,
    Error,
    IsA,
    Object,
    StaticType,
    ToValue,
    Type,
    TypedValue,
    Value,
};

pub use ffi::GtkAccelFlags as AccelFlags;
pub use ffi::GtkAlign as Align;
pub use ffi::GtkArrowPlacement as ArrowPlacement;
pub use ffi::GtkArrowType as ArrowType;
pub use ffi::GtkAttachOptions as AttachOptions;
pub use ffi::GtkBaselinePosition as BaselinePosition;
pub use ffi::GtkBorderStyle as BorderStyle;
pub use ffi::GtkBuilderError as BuilderError;
pub use ffi::GtkButtonBoxStyle as ButtonBoxStyle;
pub use ffi::GtkButtonsType as ButtonsType;
pub use ffi::GtkCalendarDisplayOptions as CalendarDisplayOptions;
pub use ffi::GtkCellRendererState as CellRendererState;
pub use ffi::GtkCornerType as CornerType;
pub use ffi::GtkDeleteType as DeleteType;
pub use ffi::GtkDestDefaults as DestDefaults;
pub use ffi::GtkDialogFlags as DialogFlags;
pub use ffi::GtkDirectionType as DirectionType;
pub use ffi::GtkDragResult as DragResult;
pub use ffi::GtkEntryIconPosition as EntryIconPosition;
pub use ffi::GtkEventSequenceState as EventSequenceState;
pub use ffi::GtkExpanderStyle as ExpanderStyle;
pub use ffi::GtkFileChooserAction as FileChooserAction;
pub use ffi::GtkFileFilterFlags as FileFilterFlags;
pub use ffi::GtkIMPreeditStyle as IMPreeditStyle;
pub use ffi::GtkIMStatusStyle as IMStatusStyle;
pub use ffi::GtkIconSize as IconSize;
pub use ffi::GtkIconViewDropPosition as IconViewDropPosition;
pub use ffi::GtkImageType as ImageType;
pub use ffi::GtkInputHints as InputHints;
pub use ffi::GtkInputPurpose as InputPurpose;
pub use ffi::GtkJunctionSides as JunctionSides;
pub use ffi::GtkJustification as Justification;
pub use ffi::GtkLevelBarMode as LevelBarMode;
pub use ffi::GtkLicense as License;
pub use ffi::GtkMessageType as MessageType;
pub use ffi::GtkMovementStep as MovementStep;
pub use ffi::GtkNumberUpLayout as NumberUpLayout;
pub use ffi::GtkOrientation as Orientation;
pub use ffi::GtkPackType as PackType;
pub use ffi::GtkPageOrientation as PageOrientation;
pub use ffi::GtkPageSet as PageSet;
pub use ffi::GtkPathPriorityType as PathPriorityType;
pub use ffi::GtkPathType as PathType;
pub use ffi::GtkPlacesOpenFlags as PlacesOpenFlags;
pub use ffi::GtkPolicyType as PolicyType;
pub use ffi::GtkPositionType as PositionType;
pub use ffi::GtkPrintDuplex as PrintDuplex;
pub use ffi::GtkPrintPages as PrintPages;
pub use ffi::GtkPrintQuality as PrintQuality;
pub use ffi::GtkPropagationPhase as PropagationPhase;
pub use ffi::GtkRecentFilterFlags as RecentFilterFlags;
pub use ffi::GtkRecentSortType as RecentSortType;
pub use ffi::GtkRegionFlags as RegionFlags;
pub use ffi::GtkReliefStyle as ReliefStyle;
pub use ffi::GtkResizeMode as ResizeMode;
pub use ffi::GtkResponseType as ResponseType;
pub use ffi::GtkRevealerTransitionType as RevealerTransitionType;
pub use ffi::GtkScrollStep as ScrollStep;
pub use ffi::GtkScrollType as ScrollType;
pub use ffi::GtkScrollablePolicy as ScrollablePolicy;
pub use ffi::GtkSelectionMode as SelectionMode;
pub use ffi::GtkSensitivityType as SensitivityType;
pub use ffi::GtkShadowType as ShadowType;
pub use ffi::GtkSizeGroupMode as SizeGroupMode;
pub use ffi::GtkSizeRequestMode as SizeRequestMode;
pub use ffi::GtkSortType as SortType;
pub use ffi::GtkSpinButtonUpdatePolicy as SpinButtonUpdatePolicy;
pub use ffi::GtkSpinType as SpinType;
pub use ffi::GtkStackTransitionType as StackTransitionType;
pub use ffi::GtkStateFlags as StateFlags;
pub use ffi::GtkStateType as StateType;
pub use ffi::GtkTextDirection as TextDirection;
pub use ffi::GtkTextSearchFlags as TextSearchFlags;
pub use ffi::GtkTextWindowType as TextWindowType;
pub use ffi::GtkToolPaletteDragTargets as ToolPaletteDragTargets;
pub use ffi::GtkToolbarStyle as ToolbarStyle;
pub use ffi::GtkTreeModelFlags as TreeModelFlags;
pub use ffi::GtkTreeViewColumnSizing as TreeViewColumnSizing;
pub use ffi::GtkTreeViewDropPosition as TreeViewDropPosition;
pub use ffi::GtkTreeViewGridLines as TreeViewGridLines;
pub use ffi::GtkUnit as Unit;
pub use ffi::GtkWidgetHelpType as WidgetHelpType;
pub use ffi::GtkWindowPosition as WindowPosition;
pub use ffi::GtkWindowType as WindowType;
pub use ffi::GtkWrapMode as WrapMode;

pub const DIALOG_MODAL: DialogFlags = ffi::GTK_DIALOG_MODAL;

pub const STYLE_PROVIDER_PRIORITY_FALLBACK: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_FALLBACK;
pub const STYLE_PROVIDER_PRIORITY_THEME: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_THEME;
pub const STYLE_PROVIDER_PRIORITY_SETTINGS: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_SETTINGS;
pub const STYLE_PROVIDER_PRIORITY_APPLICATION: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_APPLICATION;
pub const STYLE_PROVIDER_PRIORITY_USER: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_USER;

#[macro_use]
mod rt;

mod auto;

mod app_chooser;
mod builder;
mod color_button;
mod color_chooser;
mod dialog;
mod entry_buffer;
mod file_chooser_dialog;
mod list_store;
mod message_dialog;
mod notebook;
mod recent_chooser_dialog;
mod recent_data;
mod recent_info;
mod rectangle;
mod requisition;
mod signal;
#[cfg(target_os = "linux")]
mod socket;
mod text_attributes;
mod text_buffer;
mod text_iter;
mod text_view;
mod tree_model;
mod tree_path;
mod tree_store;
mod tree_view;
mod widget;

pub mod prelude;

pub use auto::*;
pub use rt::*;
pub use signal::*;

pub use rectangle::Rectangle as Allocation;
pub use app_chooser::AppChooser;
pub use builder::{Builder, Buildable};
pub use color_chooser::ColorChooser;
pub use entry_buffer::EntryBuffer;
pub use recent_data::RecentData;
pub use recent_info::RecentInfo;
pub use rectangle::Rectangle;
pub use requisition::Requisition;
#[cfg(target_os = "linux")]
pub use socket::Socket;
pub use text_attributes::TextAttributes;
<|endoftext|>


<commit_before>extern crate libc;
extern crate libtensorflow_sys;

use std::ffi::CStr;
use std::fmt;
use std::fmt::Display;
use std::fmt::Formatter;
use std::ops::Drop;

use libtensorflow_sys as tf;

////////////////////////

fn check_not_null<T>(p: *mut T) -> *mut T {
  assert!(!p.is_null());
  p
}

////////////////////////

macro_rules! impl_new {
  ($name: ident, $call:ident) => {
    impl $name {
      pub fn new() -> Self {
        unsafe {
          $name {
            inner: check_not_null(tf::$call()),
          }
        }
      }
    }
  }
}

////////////////////////

macro_rules! impl_drop {
  ($name: ident, $call:ident) => {
    impl Drop for $name {
      fn drop(&mut self) {
        unsafe {
          tf::$call(self.inner);
        }
      }
    }
  }
}

////////////////////////

macro_rules! c_enum {
  ($enum_name:ident { $($name:ident = $num:expr),* }) => {
    #[derive(PartialEq,Eq,PartialOrd,Ord,Debug)]
    pub enum $enum_name {
      UnrecognizedEnumValue(::libc::c_uint),
      $($name),*
    }

    impl $enum_name {
      #[allow(dead_code)]
      fn from_int(value: ::libc::c_uint) -> $enum_name {
        match value {
          $($num => $enum_name::$name,)*
          c => $enum_name::UnrecognizedEnumValue(c),
        }
      }

      #[allow(dead_code)]
      fn to_int(&self) -> ::libc::c_uint {
        match self {
          &$enum_name::UnrecognizedEnumValue(c) => c,
          $(&$enum_name::$name => $num),*
        }
      }
    }

    impl ::std::fmt::Display for $enum_name {
      fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match self {
          $(&$enum_name::$name => f.write_str(stringify!($name)),)*
          &$enum_name::UnrecognizedEnumValue(c) => write!(f, "UnrecognizedEnumValue({})", c),
        }
      }
    }
  };
  ($enum_name:ident { $($name:ident = $num:expr,)* }) => {
    c_enum!($enum_name { $($name = $num),* });
  }
}

////////////////////////

c_enum!(Code {
  Ok = 0,
  Cancelled = 1,
  Unknown = 2,
  InvalidArgument = 3,
  DeadlineExceeded = 4,
  NotFound = 5,
  AlreadyExists = 6,
  PermissionDenied = 7,
  ResourceExhausted = 8,
  FailedPrecondition = 9,
  Aborted = 10,
  OutOfRange = 11,
  Unimplemented = 12,
  Internal = 13,
  Unavailable = 14,
  DataLoss = 15,
  Unauthenticated = 16,
});

////////////////////////

pub struct Status {
  inner: *mut tf::TF_Status,
}

impl_new!(Status, TF_NewStatus);
impl_drop!(Status, TF_DeleteStatus);

impl Status {
  pub fn code(&self) -> Code {
    unsafe {
      Code::from_int(tf::TF_GetCode(self.inner))
    }
  }
}

impl Display for Status {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    unsafe {
      try!(write!(f, "{}: ", self.code()));
      let msg = match CStr::from_ptr(tf::TF_Message(self.inner)).to_str() {
        Ok(s) => s,
        Err(_) => "<invalid UTF-8 in message>",
      };
      f.write_str(msg)
    }
  }
}

////////////////////////

pub struct SessionOptions {
  inner: *mut tf::TF_SessionOptions,
}

impl_new!(SessionOptions, TF_NewSessionOptions);
impl_drop!(SessionOptions, TF_DeleteSessionOptions);

////////////////////////

pub struct Session {
  inner: *mut tf::TF_Session,
}

impl Session {
  pub fn new(options: &SessionOptions) -> (Option<Self>, Status) {
    let status = Status::new();
    let inner = unsafe { tf::TF_NewSession(options.inner, status.inner) };
    let session = if inner.is_null() {
      None
    } else {
      Some(Session {
        inner: inner,
      })
    };
    (session, status)
  }
}

impl Drop for Session {
  fn drop(&mut self) {
    let status = Status::new();
    unsafe {
      tf::TF_DeleteSession(self.inner, status.inner);
    }
    // TODO: What do we do with the status?
  }
}

////////////////////////

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

  #[test]
  fn smoke() {
    let options = SessionOptions::new();
    match Session::new(&options) {
      (Some(_), status) => assert_eq!(status.code(), Code::Ok),
      (None, status) => panic!("Creating session failed with status: {}", status),
    }
  }
}
<commit_msg>Add Session::close<commit_after>extern crate libc;
extern crate libtensorflow_sys;

use std::ffi::CStr;
use std::fmt;
use std::fmt::Display;
use std::fmt::Formatter;
use std::ops::Drop;

use libtensorflow_sys as tf;

////////////////////////

fn check_not_null<T>(p: *mut T) -> *mut T {
  assert!(!p.is_null());
  p
}

////////////////////////

macro_rules! impl_new {
  ($name: ident, $call:ident) => {
    impl $name {
      pub fn new() -> Self {
        unsafe {
          $name {
            inner: check_not_null(tf::$call()),
          }
        }
      }
    }
  }
}

////////////////////////

macro_rules! impl_drop {
  ($name: ident, $call:ident) => {
    impl Drop for $name {
      fn drop(&mut self) {
        unsafe {
          tf::$call(self.inner);
        }
      }
    }
  }
}

////////////////////////

macro_rules! c_enum {
  ($enum_name:ident { $($name:ident = $num:expr),* }) => {
    #[derive(PartialEq,Eq,PartialOrd,Ord,Debug)]
    pub enum $enum_name {
      UnrecognizedEnumValue(::libc::c_uint),
      $($name),*
    }

    impl $enum_name {
      #[allow(dead_code)]
      fn from_int(value: ::libc::c_uint) -> $enum_name {
        match value {
          $($num => $enum_name::$name,)*
          c => $enum_name::UnrecognizedEnumValue(c),
        }
      }

      #[allow(dead_code)]
      fn to_int(&self) -> ::libc::c_uint {
        match self {
          &$enum_name::UnrecognizedEnumValue(c) => c,
          $(&$enum_name::$name => $num),*
        }
      }
    }

    impl ::std::fmt::Display for $enum_name {
      fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match self {
          $(&$enum_name::$name => f.write_str(stringify!($name)),)*
          &$enum_name::UnrecognizedEnumValue(c) => write!(f, "UnrecognizedEnumValue({})", c),
        }
      }
    }
  };
  ($enum_name:ident { $($name:ident = $num:expr,)* }) => {
    c_enum!($enum_name { $($name = $num),* });
  }
}

////////////////////////

c_enum!(Code {
  Ok = 0,
  Cancelled = 1,
  Unknown = 2,
  InvalidArgument = 3,
  DeadlineExceeded = 4,
  NotFound = 5,
  AlreadyExists = 6,
  PermissionDenied = 7,
  ResourceExhausted = 8,
  FailedPrecondition = 9,
  Aborted = 10,
  OutOfRange = 11,
  Unimplemented = 12,
  Internal = 13,
  Unavailable = 14,
  DataLoss = 15,
  Unauthenticated = 16,
});

////////////////////////

pub struct Status {
  inner: *mut tf::TF_Status,
}

impl_new!(Status, TF_NewStatus);
impl_drop!(Status, TF_DeleteStatus);

impl Status {
  pub fn code(&self) -> Code {
    unsafe {
      Code::from_int(tf::TF_GetCode(self.inner))
    }
  }

  pub fn is_ok(&self) -> bool {
    self.code() == Code::Ok
  }
}

impl Display for Status {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    unsafe {
      try!(write!(f, "{}: ", self.code()));
      let msg = match CStr::from_ptr(tf::TF_Message(self.inner)).to_str() {
        Ok(s) => s,
        Err(_) => "<invalid UTF-8 in message>",
      };
      f.write_str(msg)
    }
  }
}

////////////////////////

pub struct SessionOptions {
  inner: *mut tf::TF_SessionOptions,
}

impl_new!(SessionOptions, TF_NewSessionOptions);
impl_drop!(SessionOptions, TF_DeleteSessionOptions);

////////////////////////

pub struct Session {
  inner: *mut tf::TF_Session,
}

impl Session {
  pub fn new(options: &SessionOptions) -> (Option<Self>, Status) {
    let status = Status::new();
    let inner = unsafe { tf::TF_NewSession(options.inner, status.inner) };
    let session = if inner.is_null() {
      None
    } else {
      Some(Session {
        inner: inner,
      })
    };
    (session, status)
  }

  pub fn close(&mut self) -> Status {
    let status = Status::new();
    unsafe {
      tf::TF_CloseSession(self.inner, status.inner);
    }
    status
  }
}

impl Drop for Session {
  fn drop(&mut self) {
    let status = Status::new();
    unsafe {
      tf::TF_DeleteSession(self.inner, status.inner);
    }
    // TODO: What do we do with the status?
  }
}

////////////////////////

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

  fn create_session() -> Session {
    let options = SessionOptions::new();
    match Session::new(&options) {
      (Some(session), status) => {
        assert_eq!(status.code(), Code::Ok);
        session
      },
      (None, status) => panic!("Creating session failed with status: {}", status),
    }
  }

  #[test]
  fn smoke() {
    create_session();
  }

  #[test]
  fn test_close() {
    let status = create_session().close();
    assert!(status.is_ok());
  }
}
<|endoftext|>


<commit_before>// Copyright 2016 ZFilexfer Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

extern crate crc;
extern crate czmq;
extern crate rustc_serialize;
#[cfg(test)]
extern crate tempdir;
extern crate zdaemon;

mod arbitrator;
mod chunk;
mod error;
mod file;
mod server;

pub use file::{File, Options as FileOptions};
pub use server::Server;
<commit_msg>Export Error struct<commit_after>// Copyright 2016 ZFilexfer Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

extern crate crc;
extern crate czmq;
extern crate rustc_serialize;
#[cfg(test)]
extern crate tempdir;
extern crate zdaemon;

mod arbitrator;
mod chunk;
mod error;
mod file;
mod server;

pub use error::Error;
pub use file::{File, Options as FileOptions};
pub use server::Server;
<|endoftext|>


<commit_before>#![deny(
    missing_docs,
    missing_debug_implementations, missing_copy_implementations,
    trivial_casts, trivial_numeric_casts,
    unsafe_code, unstable_features,
    unused_import_braces, unused_qualifications
)]

//! `merkle_sigs` implements Merkle signatures in Rust.

#[doc(no_inline)]
extern crate lamport_sigs;
extern crate merkle;
extern crate ring;

mod signatures;
pub use signatures::{MerkleSignature, MerkleSignedData, verify_data_vec_signature, sign_data_vec};

pub use merkle::Proof;

pub use lamport_sigs::PublicKey;

#[cfg(test)]
mod tests;
<commit_msg>Cleaning up imports.<commit_after>#![deny(
    missing_docs,
    missing_debug_implementations, missing_copy_implementations,
    trivial_casts, trivial_numeric_casts,
    unsafe_code, unstable_features,
    unused_import_braces, unused_qualifications
)]

//! `merkle_sigs` implements Merkle signatures in Rust.

#![deny(
    // missing_docs,
    missing_debug_implementations, missing_copy_implementations,
    trivial_casts, trivial_numeric_casts,
    unsafe_code, unstable_features,
    unused_import_braces, unused_qualifications
)]

#[doc(no_inline)]
extern crate lamport_sigs;
extern crate merkle;
extern crate ring;

mod signatures;

pub use merkle::Proof;

pub use lamport_sigs::PublicKey;
pub use signatures::{
    MerkleSignature,
    MerkleSignedData,
    verify_data_vec_signature,
    sign_data_vec
};

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>//! # Serde XML
//!
//! XML is a flexible markup language that is still used for sharing data between applications or
//! for writing configuration files.
//!
//! Serde XML provides a way to convert between text and strongly-typed Rust data structures.
//!
//! ## Caveats
//!
//! The Serde framework was mainly designed with formats such as JSON or YAML in mind.
//! As opposed to XML, these formats have the advantage of a stricter syntax which makes it
//! possible to know what type a field is without relying on an accompanying schema,
//! and disallows repeating the same tag multiple times in the same object.
//!
//! For example, encoding the following document in YAML is not trivial.
//!
//! ```xml
//! <document>
//!   <header>A header</header>
//!   <section>First section</section>
//!   <section>Second section</section>
//!   <sidenote>A sidenote</sidenote>
//!   <section>Third section</section>
//!   <sidenote>Another sidenote</sidenote>
//!   <section>Fourth section</section>
//!   <footer>The footer</footer>
//! </document>
//! ```
//!
//! One possibility is the following YAML document.
//!
//! ```yaml
//! - header: A header
//! - section: First section
//! - section: Second section
//! - sidenote: A sidenote
//! - section: Third section
//! - sidenote: Another sidenote
//! - section: Fourth section
//! - footer: The footer
//! ```
//!
//! Other notable differences:
//! - XML requires a named root node.
//! - XML has a namespace system.
//! - XML distinguishes between attributes, child tags and contents.
//! - In XML, the order of nodes is sometimes important.
//!
//! ## Basic example
//!
//! ```rust
//! use serde;
//! use serde_derive::{Deserialize, Serialize};
//! use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Item {
//!     name: String,
//!     source: String,
//! }
//!
//! fn main() {
//!     let src = r#"<Item><name>Banana</name><source>Store</source></Item>"#;
//!     let should_be = Item {
//!         name: "Banana".to_string(),
//!         source: "Store".to_string(),
//!     };
//!
//!     let item: Item = from_str(src).unwrap();
//!     assert_eq!(item, should_be);
//!
//!     let reserialized_item = to_string(&item).unwrap();
//!     assert_eq!(src, reserialized_item);
//! }
//! ```
//!
//! ## Tag contents
//!
//! ```rust
//! # use serde;
//! # use serde_derive::{Deserialize, Serialize};
//! # use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Document {
//!     content: Content
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Content {
//!     #[serde(rename = "$value")]
//!     value: String
//! }
//!
//! fn main() {
//!     let src = r#"<document><content>Lorem ipsum</content></document>"#;
//!     let document: Document = from_str(src).unwrap();
//!     assert_eq!(document.content.value, "Lorem ipsum");
//! }
//! ```
//!
//! ## Repeated tags
//!
//! ```rust
//! # use serde;
//! # use serde_derive::{Deserialize, Serialize};
//! # use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct PlateAppearance {
//!     #[serde(rename = "$value")]
//!     events: Vec<Event>
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! #[serde(rename_all = "kebab-case")]
//! enum Event {
//!     Pitch(Pitch),
//!     Runner(Runner),
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Pitch {
//!     speed: u32,
//!     r#type: PitchType,
//!     outcome: PitchOutcome,
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! enum PitchType { FourSeam, TwoSeam, Changeup, Cutter, Curve, Slider, Knuckle, Pitchout }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! enum PitchOutcome { Ball, Strike, Hit }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Runner {
//!     from: Base, to: Option<Base>, outcome: RunnerOutcome,
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! enum Base { First, Second, Third, Home }
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! enum RunnerOutcome { Steal, Caught, PickOff }
//!
//! fn main() {
//!     let document = r#"
//!         <plate-appearance>
//!           <pitch speed="95" type="FourSeam" outcome="Ball" />
//!           <pitch speed="91" type="FourSeam" outcome="Strike" />
//!           <pitch speed="85" type="Changeup" outcome="Ball" />
//!           <runner from="First" to="Second" outcome="Steal" />
//!           <pitch speed="89" type="Slider" outcome="Strike" />
//!           <pitch speed="88" type="Curve" outcome="Hit" />
//!         </plate-appearance>"#;
//!     let plate_appearance: PlateAppearance = from_str(document).unwrap();
//!     assert_eq!(plate_appearance.events[0], Event::Pitch(Pitch { speed: 95, r#type: PitchType::FourSeam, outcome: PitchOutcome::Ball }));
//! }
//! ```

pub mod de;
mod error;
pub mod ser;

pub use crate::de::{from_reader, from_str, Deserializer};
pub use crate::error::Error;
pub use crate::ser::{to_string, to_writer, Serializer};
pub use xml::reader::{EventReader, ParserConfig};
<commit_msg>📝 Example with EventReader (#163)<commit_after>//! # Serde XML
//!
//! XML is a flexible markup language that is still used for sharing data between applications or
//! for writing configuration files.
//!
//! Serde XML provides a way to convert between text and strongly-typed Rust data structures.
//!
//! ## Caveats
//!
//! The Serde framework was mainly designed with formats such as JSON or YAML in mind.
//! As opposed to XML, these formats have the advantage of a stricter syntax which makes it
//! possible to know what type a field is without relying on an accompanying schema,
//! and disallows repeating the same tag multiple times in the same object.
//!
//! For example, encoding the following document in YAML is not trivial.
//!
//! ```xml
//! <document>
//!   <header>A header</header>
//!   <section>First section</section>
//!   <section>Second section</section>
//!   <sidenote>A sidenote</sidenote>
//!   <section>Third section</section>
//!   <sidenote>Another sidenote</sidenote>
//!   <section>Fourth section</section>
//!   <footer>The footer</footer>
//! </document>
//! ```
//!
//! One possibility is the following YAML document.
//!
//! ```yaml
//! - header: A header
//! - section: First section
//! - section: Second section
//! - sidenote: A sidenote
//! - section: Third section
//! - sidenote: Another sidenote
//! - section: Fourth section
//! - footer: The footer
//! ```
//!
//! Other notable differences:
//! - XML requires a named root node.
//! - XML has a namespace system.
//! - XML distinguishes between attributes, child tags and contents.
//! - In XML, the order of nodes is sometimes important.
//!
//! ## Basic example
//!
//! ```rust
//! use serde;
//! use serde_derive::{Deserialize, Serialize};
//! use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Item {
//!     name: String,
//!     source: String,
//! }
//!
//! fn main() {
//!     let src = r#"<Item><name>Banana</name><source>Store</source></Item>"#;
//!     let should_be = Item {
//!         name: "Banana".to_string(),
//!         source: "Store".to_string(),
//!     };
//!
//!     let item: Item = from_str(src).unwrap();
//!     assert_eq!(item, should_be);
//!
//!     let reserialized_item = to_string(&item).unwrap();
//!     assert_eq!(src, reserialized_item);
//! }
//! ```
//!
//! ## Tag contents
//!
//! ```rust
//! # use serde;
//! # use serde_derive::{Deserialize, Serialize};
//! # use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Document {
//!     content: Content
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Content {
//!     #[serde(rename = "$value")]
//!     value: String
//! }
//!
//! fn main() {
//!     let src = r#"<document><content>Lorem ipsum</content></document>"#;
//!     let document: Document = from_str(src).unwrap();
//!     assert_eq!(document.content.value, "Lorem ipsum");
//! }
//! ```
//!
//! ## Repeated tags
//!
//! ```rust
//! # use serde;
//! # use serde_derive::{Deserialize, Serialize};
//! # use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct PlateAppearance {
//!     #[serde(rename = "$value")]
//!     events: Vec<Event>
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! #[serde(rename_all = "kebab-case")]
//! enum Event {
//!     Pitch(Pitch),
//!     Runner(Runner),
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Pitch {
//!     speed: u32,
//!     r#type: PitchType,
//!     outcome: PitchOutcome,
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! enum PitchType { FourSeam, TwoSeam, Changeup, Cutter, Curve, Slider, Knuckle, Pitchout }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! enum PitchOutcome { Ball, Strike, Hit }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Runner {
//!     from: Base, to: Option<Base>, outcome: RunnerOutcome,
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! enum Base { First, Second, Third, Home }
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! enum RunnerOutcome { Steal, Caught, PickOff }
//!
//! fn main() {
//!     let document = r#"
//!         <plate-appearance>
//!           <pitch speed="95" type="FourSeam" outcome="Ball" />
//!           <pitch speed="91" type="FourSeam" outcome="Strike" />
//!           <pitch speed="85" type="Changeup" outcome="Ball" />
//!           <runner from="First" to="Second" outcome="Steal" />
//!           <pitch speed="89" type="Slider" outcome="Strike" />
//!           <pitch speed="88" type="Curve" outcome="Hit" />
//!         </plate-appearance>"#;
//!     let plate_appearance: PlateAppearance = from_str(document).unwrap();
//!     assert_eq!(plate_appearance.events[0], Event::Pitch(Pitch { speed: 95, r#type: PitchType::FourSeam, outcome: PitchOutcome::Ball }));
//! }
//! ```
//!
//! ## Custom EventReader
//!
//! ```rust
//! use serde::Deserialize;
//! use serde_derive::{Deserialize, Serialize};
//! use serde_xml_rs::{from_str, to_string, de::Deserializer};
//! use xml::reader::{EventReader, ParserConfig};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Item {
//!     name: String,
//!     source: String,
//! }
//!
//! fn main() {
//!     let src = r#"<Item><name>  Banana  </name><source>Store</source></Item>"#;
//!     let should_be = Item {
//!         name: "  Banana  ".to_string(),
//!         source: "Store".to_string(),
//!     };
//!
//!     let config = ParserConfig::new()
//!         .trim_whitespace(false)
//!         .whitespace_to_characters(true);
//!     let event_reader = EventReader::new_with_config(src.as_bytes(), config);
//!     let item = Item::deserialize(&mut Deserializer::new(event_reader)).unwrap();
//!     assert_eq!(item, should_be);
//! }
//! ```
//!

pub mod de;
mod error;
pub mod ser;

pub use crate::de::{from_reader, from_str, Deserializer};
pub use crate::error::Error;
pub use crate::ser::{to_string, to_writer, Serializer};
pub use xml::reader::{EventReader, ParserConfig};
<|endoftext|>


<commit_before>//! # Convert Sort Expression to SQL
//!
//! Converts 'sort format' to 'SQL format'. E.g.:
//!
//! - `-id` -> `id DESC NULLS LAST`
//! - `id`  -> `id ASC NULLS LAST`
//! - `id-` -> `id ASC NULLS FIRST`
//! - `-aired,id` -> `aired DESC NULLS LAST, id ASC NULLS LAST`
//!
//! # Example
//!
//! ```
//! # use sort_str_to_sql::{sort_str_to_sql};
//! assert!(
//!   sort_str_to_sql("-id") ==
//!   Some("id DESC NULLS LAST".to_string())
//! )
//! assert!(
//!   sort_str_to_sql("-id,+aired-") ==
//!   Some("id DESC NULLS LAST, aired ASC NULLS FIRST".to_string())
//! )
//! ```
//!
//! (See tests for more examples.)
#![crate_name = "sort_str_to_sql"]

#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
#[cfg(test)] extern crate test;

static SORT_STR_FORMAT: regex::Regex = regex!(
    r"^(?P<order>[+-]?)(?P<field>[\w.]+)(?P<nulls>[-]?)$"
);

/// Convert One Sort Expression to SQL
fn convert_one_sort_str_field_to_sql(sort_str: &str) -> Option<String> {
    let fields = match SORT_STR_FORMAT.captures(sort_str) {
        Some(captures) => captures,
        None => return None,
    };

    let field = fields.name("field");
    let order = match fields.name("order") {
        "-" => "DESC",
        _   => "ASC",
    };
    let nulls = match fields.name("nulls") {
        "-" => "NULLS FIRST",
        _   => "NULLS LAST",
    };

    let sql = format!("{} {} {}", field, order, nulls);
    return Some(sql);
}

/// Convert Sort Expression to SQL
pub fn sort_str_to_sql(sort_str: &str) -> Option<String> {
    let sql_array: Vec<String> = sort_str.split(',')
    .filter_map(convert_one_sort_str_field_to_sql)
    .collect();

    let sql = sql_array.connect(", ");
    return if sql.as_slice() == "" { None } else { Some(sql) };
}

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

    use super::{sort_str_to_sql};

    #[test]
    fn it_works() {
        let tests = vec![
            // Correct inputs
            ("id", Some("id ASC NULLS LAST")),
            ("+id", Some("id ASC NULLS LAST")),
            ("-id", Some("id DESC NULLS LAST")),
            ("id-", Some("id ASC NULLS FIRST")),
            ("+id-", Some("id ASC NULLS FIRST")),
            ("-id-", Some("id DESC NULLS FIRST")),
            ("show.id", Some("show.id ASC NULLS LAST")),
            ("-id,aired-", Some("id DESC NULLS LAST, aired ASC NULLS FIRST")),
            ("-id,+aired-", Some("id DESC NULLS LAST, aired ASC NULLS FIRST")),
            ("+id-,show.id", Some("id ASC NULLS FIRST, show.id ASC NULLS LAST")),

            // Incorrect inputs
            ("lol what", None),
            ("+-id-", None),

            // Partially correct inputs
            ("id,++aired+", Some("id ASC NULLS LAST")),
            ("?id,+aired-", Some("aired ASC NULLS FIRST")),
        ];

        for &(input, _sql) in tests.iter() {
            let sql = match _sql { None => None, Some(s) => Some(s.to_string())};
            assert!(
                sort_str_to_sql(input) == sql,
                "FAILED `{}` => `{}` NOT `{}`", input, sort_str_to_sql(input), sql
            )
        }
    }

    #[bench]
    fn bench_simple(b: &mut Bencher) {
        b.iter(|| sort_str_to_sql("id"));
    }

    #[bench]
    fn bench_complex(b: &mut Bencher) {
        b.iter(|| sort_str_to_sql("-date,+id-,show.id"));
    }

}
<commit_msg>Fixes for Regex Changes in Rust Nightly<commit_after>//! # Convert Sort Expression to SQL
//!
//! Converts 'sort format' to 'SQL format'. E.g.:
//!
//! - `-id` -> `id DESC NULLS LAST`
//! - `id`  -> `id ASC NULLS LAST`
//! - `id-` -> `id ASC NULLS FIRST`
//! - `-aired,id` -> `aired DESC NULLS LAST, id ASC NULLS LAST`
//!
//! # Example
//!
//! ```
//! # use sort_str_to_sql::{sort_str_to_sql};
//! assert!(
//!   sort_str_to_sql("-id") ==
//!   Some("id DESC NULLS LAST".to_string())
//! );
//! assert!(
//!   sort_str_to_sql("-id,+aired-") ==
//!   Some("id DESC NULLS LAST, aired ASC NULLS FIRST".to_string())
//! );
//! ```
//!
//! (See tests for more examples.)
#![crate_name = "sort_str_to_sql"]

#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
#[cfg(test)] extern crate test;

/// Convert One Sort Expression to SQL
fn convert_one_sort_str_field_to_sql(sort_str: &str) -> Option<String> {
    let sort_str_format = regex!(
        r"^(?P<order>[+-]?)(?P<field>[\w.]+)(?P<nulls>[-]?)$"
    );

    let fields = match sort_str_format.captures(sort_str) {
        Some(captures) => captures,
        None => return None,
    };

    let field = match fields.name("field") {
        Some(f) => f,
        None => return None,
    };

    let order = match fields.name("order") {
        Some("-") => "DESC",
        _   => "ASC",
    };
    let nulls = match fields.name("nulls") {
        Some("-") => "NULLS FIRST",
        _   => "NULLS LAST",
    };

    let sql = format!("{} {} {}", field, order, nulls);
    return Some(sql);
}

/// Convert Sort Expression to SQL
pub fn sort_str_to_sql(sort_str: &str) -> Option<String> {
    let sql_array: Vec<String> = sort_str.split(',')
    .filter_map(convert_one_sort_str_field_to_sql)
    .collect();

    let sql = sql_array.connect(", ");
    return if sql.as_slice() == "" { None } else { Some(sql) };
}

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

    use super::{sort_str_to_sql};

    #[test]
    fn it_works() {
        let tests = vec![
            // Correct inputs
            ("id", Some("id ASC NULLS LAST")),
            ("+id", Some("id ASC NULLS LAST")),
            ("-id", Some("id DESC NULLS LAST")),
            ("id-", Some("id ASC NULLS FIRST")),
            ("+id-", Some("id ASC NULLS FIRST")),
            ("-id-", Some("id DESC NULLS FIRST")),
            ("show.id", Some("show.id ASC NULLS LAST")),
            ("-id,aired-", Some("id DESC NULLS LAST, aired ASC NULLS FIRST")),
            ("-id,+aired-", Some("id DESC NULLS LAST, aired ASC NULLS FIRST")),
            ("+id-,show.id", Some("id ASC NULLS FIRST, show.id ASC NULLS LAST")),

            // Incorrect inputs
            ("lol what", None),
            ("+-id-", None),

            // Partially correct inputs
            ("id,++aired+", Some("id ASC NULLS LAST")),
            ("?id,+aired-", Some("aired ASC NULLS FIRST")),
        ];

        for &(input, _sql) in tests.iter() {
            let sql = match _sql { None => None, Some(s) => Some(s.to_string())};
            assert!(
                sort_str_to_sql(input) == sql,
                "FAILED `{}` => `{}` NOT `{}`", input, sort_str_to_sql(input), sql
            )
        }
    }

    #[bench]
    fn bench_simple(b: &mut Bencher) {
        b.iter(|| sort_str_to_sql("id"));
    }

    #[bench]
    fn bench_complex(b: &mut Bencher) {
        b.iter(|| sort_str_to_sql("-date,+id-,show.id"));
    }

}
<|endoftext|>


<commit_before>extern crate itertools;

use itertools::Itertools;

use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;

mod prim;

#[derive(Debug, Clone)]
pub enum EvalError {
    StackUnderflow,
    NotFound(String),
    TypeMismatch,
}

impl fmt::Display for EvalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            EvalError::StackUnderflow => write!(f, "stack underflow"),
            EvalError::NotFound(ref name) => write!(f, "could not find `{}`", name),
            EvalError::TypeMismatch => write!(f, "type mismatch"),
        }
    }
}

pub type EvalResult = Result<Stack, EvalError>;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Value {
    Bool(bool),
    Number(i32),
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Bool(x) => write!(f, "{}", x),
            Value::Number(x) => write!(f, "{}", x),
        }
    }
}

pub type PrimFn = fn(Stack, &Words) -> EvalResult;

// The type `fn(T, &U) -> V` does not implement `Debug`, `Clone`, or
// `PartialEq`, so to enable `#[derive(..)]` to work for `Term`, we implement
// these for a wrapper struct.
#[derive(Copy)]
pub struct Prim {
    f: PrimFn,
}

impl fmt::Debug for Prim {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Prim(..)")
    }
}

impl Clone for Prim {
    fn clone(&self) -> Prim { Prim { f: self.f } }
}

impl PartialEq for Prim {
    fn eq(&self, other: &Prim) -> bool {
        &self.f as *const _ == &other.f as *const _
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Term {
    Push(Value),
    Quote(Stack),
    Call(String),
    Prim(Prim),
}

impl Term {
    pub fn prim(f: PrimFn) -> Term {
        Term::Prim(Prim { f: f })
    }
}

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Term::Push(value) => write!(f, "{}", value),
            Term::Quote(ref stack) => write!(f, "[ {} ]", stack),
            Term::Call(ref name) => write!(f, "{}", name),
            Term::Prim(_) => write!(f, "<prim>"),
        }
    }
}

#[derive(Clone, Debug)]
pub struct Words {
    defs: HashMap<String, Term>,
}

impl Words {
    pub fn empty() -> Words {
        Words {
            defs: HashMap::new(),
        }
    }

    pub fn standard() -> Words {
        let mut words = Words::empty();

        words.define("words", Term::prim(prim::words)); // (A ~> A)

        words.define("dup", Term::prim(prim::dup)); // (A b -> A b b)
        words.define("pop", Term::prim(prim::pop)); // (A b -> A)
        words.define("swap", Term::prim(prim::swap)); // (A b c -> A c b)
        words.define("apply", Term::prim(prim::apply)); // (A (A -> B) -> B)
        words.define("quote", Term::prim(prim::quote)); // (A b -> A (C -> C b))
        words.define("compose", Term::prim(prim::compose)); // (A (B -> C) (C -> D) -> A (B -> D)))

        words.define("if", Term::prim(prim::if_)); // (A bool (A -> B) (A -> B) -> B)

        words.define("true", Term::Push(Value::Bool(true))); // (A -> A bool)
        words.define("false", Term::Push(Value::Bool(false))); // (A -> A bool)

        words.define("eq", Term::prim(prim::eq)); // (A num num -> A bool)
        words.define("and", Term::prim(prim::and)); // (A bool bool -> A bool)
        words.define("or", Term::prim(prim::or)); // (A bool bool -> A bool)
        words.define("not", Term::prim(prim::not)); // (A bool -> A bool)

        words.define("+", Term::prim(prim::add)); // (A num num -> A num)
        words.define("-", Term::prim(prim::sub)); // (A num num -> A num)
        words.define("*", Term::prim(prim::mul)); // (A num num -> A num)
        words.define("/", Term::prim(prim::div)); // (A num num -> A num)
        words.define("%", Term::prim(prim::rem)); // (A num num -> A num)

        words
    }

    pub fn define<S: Into<String>>(&mut self, name: S, x: Term) {
        self.defs.insert(name.into(), x);
    }

    pub fn lookup(&self, name: &str) -> Option<&Term> {
        self.defs.get(name)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Stack {
    terms: Vec<Term>,
}

impl Stack {
    pub fn new(terms: Vec<Term>) -> Stack {
        Stack { terms: terms }
    }

    pub fn empty() -> Stack {
        Stack::new(vec![])
    }

    fn push(mut self, term: Term) -> Stack {
        self.terms.push(term);
        self
    }

    fn pop(mut self) -> Result<(Stack, Term), EvalError> {
        match self.terms.pop() {
            Some(term) => Ok((self, term)),
            None => Err(EvalError::StackUnderflow),
        }
    }

    fn pop_bool(self) -> Result<(Stack, bool), EvalError> {
        let (stack, term) = try!(self.pop());
        match term {
            Term::Push(Value::Bool(x)) => Ok((stack, x)),
            _ => Err(EvalError::TypeMismatch),
        }
    }

    fn pop_number(self) -> Result<(Stack, i32), EvalError> {
        let (stack, term) = try!(self.pop());
        match term {
            Term::Push(Value::Number(x)) => Ok((stack, x)),
            _ => Err(EvalError::TypeMismatch),
        }
    }

    fn pop_quote(self) -> Result<(Stack, Stack), EvalError> {
        let (stack, term) = try!(self.pop());
        match term {
            Term::Quote(quoted) => Ok((stack, quoted)),
            _ => Err(EvalError::TypeMismatch),
        }
    }

    fn peek(&self) -> Result<&Term, EvalError> {
        match self.terms.last() {
            Some(term) => Ok(term),
            None => Err(EvalError::StackUnderflow),
        }
    }

    fn eval_name(self, words: &Words, name: String) -> EvalResult {
        match words.lookup(&name) {
            Some(term) => self.eval_term(words, term.clone()),
            None => Err(EvalError::NotFound(name)),
        }
    }

    fn eval_term(self, words: &Words, term: Term) -> EvalResult {
        match term {
            Term::Push(value) => Ok(self.push(Term::Push(value))),
            Term::Quote(stack) => Ok(self.push(Term::Quote(stack))),
            Term::Call(name) => self.eval_name(words, name),
            Term::Prim(Prim { f }) => f(self, words),
        }
    }

    fn eval_stack(mut self, words: &Words, quote: Stack) -> EvalResult {
        let mut terms = quote.terms.into_iter();
        while let Some(term) = terms.next() {
            self = try!(self.eval_term(words, term));
        }
        Ok(self)
    }
}

pub fn eval(stack: Stack, words: &Words) -> EvalResult {
    Stack::empty().eval_stack(words, stack)
}

impl FromStr for Stack {
    type Err = String;

    fn from_str(src: &str) -> Result<Stack, String> {
        fn parse_tokens<'a, I>(tokens: &mut I, in_quote: bool) -> Result<Stack, String> where
            I: Iterator<Item = &'a str>,
        {
            let mut terms = vec![];

            while let Some(token) = tokens.next() {
                match token {
                    "[" => {
                        terms.push(Term::Quote(
                            try!(parse_tokens(tokens, true))
                        ))
                    },
                    "]" => {
                        if in_quote {
                            return Ok(Stack::new(terms));
                        } else {
                            return Err("found unexpected `]`".to_string());
                        }
                    },
                    token => match token.parse() {
                        Ok(x) => terms.push(Term::Push(Value::Number(x))),
                        Err(_) => terms.push(Term::Call(token.to_string())),
                    },
                }
            }

            if in_quote {
                Err("expected closing `]`".to_string())
            } else {
                Ok(Stack::new(terms))
            }
        }

        parse_tokens(&mut src.split_whitespace(), false)
    }
}

impl fmt::Display for Stack {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.terms.iter().format(" ", |t, f| f(t)))
    }
}

#[cfg(test)]
mod tests {
    mod prim {
        mod eq {
            use Prim;
            use prim;

            #[test]
            fn test_same() {
                assert_eq!(Prim(prim::eq), Prim(prim::eq));
                assert_eq!(Prim(prim::add), Prim(prim::add));
            }

            #[test]
            fn test_different() {
                assert!(Prim(prim::eq) != Prim(prim::add));
                assert!(Prim(prim::add) != Prim(prim::eq));
            }
        }
    }

    mod stack {
        mod parse {
            use Stack;
            use Term::*;
            use Value::*;

            #[test]
            fn test_number() {
                assert_eq!("123".parse(), Ok(Stack::new(vec![Push(Number(123))])));
                assert_eq!(" 34 ".parse(), Ok(Stack::new(vec![Push(Number(34))])));
            }

            #[test]
            fn test_name() {
                assert_eq!("foo".parse(), Ok(Stack::new(vec![Call("foo".to_string())])));
                assert_eq!(" * ".parse(), Ok(Stack::new(vec![Call("*".to_string())])));
            }

            #[test]
            fn test_quote() {
                assert_eq!("[ foo ]".parse(),
                    Ok(Stack::new(vec![
                        Quote(Stack::new(vec![Call("foo".to_string())]))
                    ])));

                assert_eq!("[ 1 2 * + ]".parse(),
                    Ok(Stack::new(vec![
                        Quote(Stack::new(vec![
                            Push(Number(1)),
                            Push(Number(2)),
                            Call("*".to_string()),
                            Call("+".to_string()),
                        ])),
                    ])));
            }

            #[test]
            fn test_compose() {
                assert_eq!(" 1 2 [ foo ]  * +".parse(),
                    Ok(Stack::new(vec![
                        Push(Number(1)),
                        Push(Number(2)),
                        Quote(Stack::new(vec![Call("foo".to_string())])),
                        Call("*".to_string()),
                        Call("+".to_string()),
                    ])));
                assert_eq!(" 1 2 [ foo [ -23 bar ] ]  * +".parse(),
                    Ok(Stack::new(vec![
                        Push(Number(1)),
                        Push(Number(2)),
                        Quote(Stack::new(vec![
                            Call("foo".to_string()),
                            Quote(Stack::new(vec![
                                Push(Number(-23)),
                                Call("bar".to_string())
                            ]))
                        ])),
                        Call("*".to_string()),
                        Call("+".to_string()),
                    ])));
            }
        }
    }
}
<commit_msg>Print empty stacks correctly<commit_after>extern crate itertools;

use itertools::Itertools;

use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;

mod prim;

#[derive(Debug, Clone)]
pub enum EvalError {
    StackUnderflow,
    NotFound(String),
    TypeMismatch,
}

impl fmt::Display for EvalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            EvalError::StackUnderflow => write!(f, "stack underflow"),
            EvalError::NotFound(ref name) => write!(f, "could not find `{}`", name),
            EvalError::TypeMismatch => write!(f, "type mismatch"),
        }
    }
}

pub type EvalResult = Result<Stack, EvalError>;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Value {
    Bool(bool),
    Number(i32),
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Bool(x) => write!(f, "{}", x),
            Value::Number(x) => write!(f, "{}", x),
        }
    }
}

pub type PrimFn = fn(Stack, &Words) -> EvalResult;

// The type `fn(T, &U) -> V` does not implement `Debug`, `Clone`, or
// `PartialEq`, so to enable `#[derive(..)]` to work for `Term`, we implement
// these for a wrapper struct.
#[derive(Copy)]
pub struct Prim {
    f: PrimFn,
}

impl fmt::Debug for Prim {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Prim(..)")
    }
}

impl Clone for Prim {
    fn clone(&self) -> Prim { Prim { f: self.f } }
}

impl PartialEq for Prim {
    fn eq(&self, other: &Prim) -> bool {
        &self.f as *const _ == &other.f as *const _
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Term {
    Push(Value),
    Quote(Stack),
    Call(String),
    Prim(Prim),
}

impl Term {
    pub fn prim(f: PrimFn) -> Term {
        Term::Prim(Prim { f: f })
    }
}

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Term::Push(value) => write!(f, "{}", value),
            Term::Quote(ref stack) if stack.terms.is_empty() => write!(f, "[ ]"),
            Term::Quote(ref stack) => write!(f, "[ {} ]", stack),
            Term::Call(ref name) => write!(f, "{}", name),
            Term::Prim(_) => write!(f, "<prim>"),
        }
    }
}

#[derive(Clone, Debug)]
pub struct Words {
    defs: HashMap<String, Term>,
}

impl Words {
    pub fn empty() -> Words {
        Words {
            defs: HashMap::new(),
        }
    }

    pub fn standard() -> Words {
        let mut words = Words::empty();

        words.define("words", Term::prim(prim::words)); // (A ~> A)

        words.define("dup", Term::prim(prim::dup)); // (A b -> A b b)
        words.define("pop", Term::prim(prim::pop)); // (A b -> A)
        words.define("swap", Term::prim(prim::swap)); // (A b c -> A c b)
        words.define("apply", Term::prim(prim::apply)); // (A (A -> B) -> B)
        words.define("quote", Term::prim(prim::quote)); // (A b -> A (C -> C b))
        words.define("compose", Term::prim(prim::compose)); // (A (B -> C) (C -> D) -> A (B -> D)))

        words.define("if", Term::prim(prim::if_)); // (A bool (A -> B) (A -> B) -> B)

        words.define("true", Term::Push(Value::Bool(true))); // (A -> A bool)
        words.define("false", Term::Push(Value::Bool(false))); // (A -> A bool)

        words.define("eq", Term::prim(prim::eq)); // (A num num -> A bool)
        words.define("and", Term::prim(prim::and)); // (A bool bool -> A bool)
        words.define("or", Term::prim(prim::or)); // (A bool bool -> A bool)
        words.define("not", Term::prim(prim::not)); // (A bool -> A bool)

        words.define("+", Term::prim(prim::add)); // (A num num -> A num)
        words.define("-", Term::prim(prim::sub)); // (A num num -> A num)
        words.define("*", Term::prim(prim::mul)); // (A num num -> A num)
        words.define("/", Term::prim(prim::div)); // (A num num -> A num)
        words.define("%", Term::prim(prim::rem)); // (A num num -> A num)

        words
    }

    pub fn define<S: Into<String>>(&mut self, name: S, x: Term) {
        self.defs.insert(name.into(), x);
    }

    pub fn lookup(&self, name: &str) -> Option<&Term> {
        self.defs.get(name)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Stack {
    terms: Vec<Term>,
}

impl Stack {
    pub fn new(terms: Vec<Term>) -> Stack {
        Stack { terms: terms }
    }

    pub fn empty() -> Stack {
        Stack::new(vec![])
    }

    fn push(mut self, term: Term) -> Stack {
        self.terms.push(term);
        self
    }

    fn pop(mut self) -> Result<(Stack, Term), EvalError> {
        match self.terms.pop() {
            Some(term) => Ok((self, term)),
            None => Err(EvalError::StackUnderflow),
        }
    }

    fn pop_bool(self) -> Result<(Stack, bool), EvalError> {
        let (stack, term) = try!(self.pop());
        match term {
            Term::Push(Value::Bool(x)) => Ok((stack, x)),
            _ => Err(EvalError::TypeMismatch),
        }
    }

    fn pop_number(self) -> Result<(Stack, i32), EvalError> {
        let (stack, term) = try!(self.pop());
        match term {
            Term::Push(Value::Number(x)) => Ok((stack, x)),
            _ => Err(EvalError::TypeMismatch),
        }
    }

    fn pop_quote(self) -> Result<(Stack, Stack), EvalError> {
        let (stack, term) = try!(self.pop());
        match term {
            Term::Quote(quoted) => Ok((stack, quoted)),
            _ => Err(EvalError::TypeMismatch),
        }
    }

    fn peek(&self) -> Result<&Term, EvalError> {
        match self.terms.last() {
            Some(term) => Ok(term),
            None => Err(EvalError::StackUnderflow),
        }
    }

    fn eval_name(self, words: &Words, name: String) -> EvalResult {
        match words.lookup(&name) {
            Some(term) => self.eval_term(words, term.clone()),
            None => Err(EvalError::NotFound(name)),
        }
    }

    fn eval_term(self, words: &Words, term: Term) -> EvalResult {
        match term {
            Term::Push(value) => Ok(self.push(Term::Push(value))),
            Term::Quote(stack) => Ok(self.push(Term::Quote(stack))),
            Term::Call(name) => self.eval_name(words, name),
            Term::Prim(Prim { f }) => f(self, words),
        }
    }

    fn eval_stack(mut self, words: &Words, quote: Stack) -> EvalResult {
        let mut terms = quote.terms.into_iter();
        while let Some(term) = terms.next() {
            self = try!(self.eval_term(words, term));
        }
        Ok(self)
    }
}

pub fn eval(stack: Stack, words: &Words) -> EvalResult {
    Stack::empty().eval_stack(words, stack)
}

impl FromStr for Stack {
    type Err = String;

    fn from_str(src: &str) -> Result<Stack, String> {
        fn parse_tokens<'a, I>(tokens: &mut I, in_quote: bool) -> Result<Stack, String> where
            I: Iterator<Item = &'a str>,
        {
            let mut terms = vec![];

            while let Some(token) = tokens.next() {
                match token {
                    "[" => {
                        terms.push(Term::Quote(
                            try!(parse_tokens(tokens, true))
                        ))
                    },
                    "]" => {
                        if in_quote {
                            return Ok(Stack::new(terms));
                        } else {
                            return Err("found unexpected `]`".to_string());
                        }
                    },
                    token => match token.parse() {
                        Ok(x) => terms.push(Term::Push(Value::Number(x))),
                        Err(_) => terms.push(Term::Call(token.to_string())),
                    },
                }
            }

            if in_quote {
                Err("expected closing `]`".to_string())
            } else {
                Ok(Stack::new(terms))
            }
        }

        parse_tokens(&mut src.split_whitespace(), false)
    }
}

impl fmt::Display for Stack {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.terms.iter().format(" ", |t, f| f(t)))
    }
}

#[cfg(test)]
mod tests {
    mod prim {
        mod eq {
            use Prim;
            use prim;

            #[test]
            fn test_same() {
                assert_eq!(Prim(prim::eq), Prim(prim::eq));
                assert_eq!(Prim(prim::add), Prim(prim::add));
            }

            #[test]
            fn test_different() {
                assert!(Prim(prim::eq) != Prim(prim::add));
                assert!(Prim(prim::add) != Prim(prim::eq));
            }
        }
    }

    mod stack {
        mod parse {
            use Stack;
            use Term::*;
            use Value::*;

            #[test]
            fn test_number() {
                assert_eq!("123".parse(), Ok(Stack::new(vec![Push(Number(123))])));
                assert_eq!(" 34 ".parse(), Ok(Stack::new(vec![Push(Number(34))])));
            }

            #[test]
            fn test_name() {
                assert_eq!("foo".parse(), Ok(Stack::new(vec![Call("foo".to_string())])));
                assert_eq!(" * ".parse(), Ok(Stack::new(vec![Call("*".to_string())])));
            }

            #[test]
            fn test_quote() {
                assert_eq!("[ foo ]".parse(),
                    Ok(Stack::new(vec![
                        Quote(Stack::new(vec![Call("foo".to_string())]))
                    ])));

                assert_eq!("[ 1 2 * + ]".parse(),
                    Ok(Stack::new(vec![
                        Quote(Stack::new(vec![
                            Push(Number(1)),
                            Push(Number(2)),
                            Call("*".to_string()),
                            Call("+".to_string()),
                        ])),
                    ])));
            }

            #[test]
            fn test_compose() {
                assert_eq!(" 1 2 [ foo ]  * +".parse(),
                    Ok(Stack::new(vec![
                        Push(Number(1)),
                        Push(Number(2)),
                        Quote(Stack::new(vec![Call("foo".to_string())])),
                        Call("*".to_string()),
                        Call("+".to_string()),
                    ])));
                assert_eq!(" 1 2 [ foo [ -23 bar ] ]  * +".parse(),
                    Ok(Stack::new(vec![
                        Push(Number(1)),
                        Push(Number(2)),
                        Quote(Stack::new(vec![
                            Call("foo".to_string()),
                            Quote(Stack::new(vec![
                                Push(Number(-23)),
                                Call("bar".to_string())
                            ]))
                        ])),
                        Call("*".to_string()),
                        Call("+".to_string()),
                    ])));
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![macro_escape]

use std::fmt;
use std::mem;
use std::ops::Index;
use std::raw::Slice;
use std::slice::AsSlice;
use matrix::Matrix;

pub struct Mat<T> {
    rows: uint,
    cols: uint,
    data: Vec<T>,
}

impl<T> Mat<T> {
    #[inline]
    pub fn new() -> Mat<T> {
        let _data: Vec<T> = Vec::new();
        Mat { rows: 0, cols: 0, data: _data }
    }

    #[inline]
    pub fn from_vec(rows: uint, cols: uint, vec: Vec<T>) -> Mat<T> {
        Mat { rows: rows, cols: cols, data: vec }
    }

    #[inline]
    pub fn zero(rows: uint, cols: uint) -> Mat<T> {
        let mut _data: Vec<T> = Vec::with_capacity(rows * cols);
        unsafe { _data.set_len(rows * cols); }
        Mat { rows: rows, cols: cols, data: _data}
    }

    #[inline]
    pub fn push(&mut self, value: T) {
        self.data.push(value);
    }

    #[inline]
    pub fn rows(&self) -> uint {
        self.rows
    }

    #[inline]
    pub fn cols(&self) -> uint {
        self.cols
    }

    #[inline]
    pub unsafe fn set_rows(&mut self, rows: uint) {
        self.rows = rows;
    }

    #[inline]
    pub unsafe fn set_cols(&mut self, cols: uint) {
        self.cols = cols;
    }

    #[inline]
    pub unsafe fn as_slice<'a>(&'a self) -> &'a [T] {
        self.data.as_slice()
    }

    #[inline]
    pub unsafe fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        self.data.as_mut_slice()
    }
}

impl<T: PartialEq> PartialEq for Mat<T> {
    fn eq(&self, other: &Mat<T>) -> bool {
        self.rows == other.rows &&
        self.cols == other.cols &&
        self.data == other.data
    }
}

impl<T> Index<uint, [T]> for Mat<T> {
    fn index<'a>(&'a self, index: &uint) -> &'a [T] {
        unsafe {
            let ptr = self.data.as_slice().as_ptr().offset((*index * self.cols) as int);
            mem::transmute(Slice { data: ptr, len: self.cols })
        }
    }
}

impl<T: fmt::Show> fmt::Show for Mat<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in range(0u, self.rows) {
            match writeln!(f, "{}", &self[i]) {
                Ok(_) => (),
                x => return x,
            }
        }

        Ok(())
    }
}

#[macro_export]
macro_rules! mat(
    ($([$($e: expr),+]),*) => ({
        // leading _ to allow empty construction without a warning.
        let mut _temp = Mat::new();
        let mut rows = 0u;
        let mut _cols;
        $(
            rows += 1;
            _cols = 0u;
            $(
                _cols += 1;
                _temp.push($e);
            )+
        )*

        unsafe {
            _temp.set_rows(rows);
            _temp.set_cols(_cols);
        }

        _temp
    });
)

#[cfg(test)]
mod tests {
    extern crate test;

    use mat::Mat;

    #[test]
    fn index() {
        let m = mat![[1f32,2f32],[3f32,4f32]];

        assert_eq!(1.0, m[0][0]);
        assert_eq!(2.0, m[0][1]);
        assert_eq!(3.0, m[1][0]);
        assert_eq!(4.0, m[1][1]);
    }
}
<commit_msg>Mat clone<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![macro_escape]

use std::fmt;
use std::mem;
use std::ops::Index;
use std::raw::Slice;
use std::slice::AsSlice;
use matrix::Matrix;
use vector::ops::Copy;

pub struct Mat<T> {
    rows: uint,
    cols: uint,
    data: Vec<T>,
}

impl<T> Mat<T> {
    #[inline]
    pub fn new() -> Mat<T> {
        let _data: Vec<T> = Vec::new();
        Mat { rows: 0, cols: 0, data: _data }
    }

    #[inline]
    pub fn from_vec(rows: uint, cols: uint, vec: Vec<T>) -> Mat<T> {
        Mat { rows: rows, cols: cols, data: vec }
    }

    #[inline]
    pub fn zero(rows: uint, cols: uint) -> Mat<T> {
        let mut _data: Vec<T> = Vec::with_capacity(rows * cols);
        unsafe { _data.set_len(rows * cols); }
        Mat { rows: rows, cols: cols, data: _data}
    }

    #[inline]
    pub fn push(&mut self, value: T) {
        self.data.push(value);
    }

    #[inline]
    pub fn rows(&self) -> uint {
        self.rows
    }

    #[inline]
    pub fn cols(&self) -> uint {
        self.cols
    }

    #[inline]
    pub unsafe fn set_rows(&mut self, rows: uint) {
        self.rows = rows;
    }

    #[inline]
    pub unsafe fn set_cols(&mut self, cols: uint) {
        self.cols = cols;
    }

    #[inline]
    pub unsafe fn as_slice<'a>(&'a self) -> &'a [T] {
        self.data.as_slice()
    }

    #[inline]
    pub unsafe fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        self.data.as_mut_slice()
    }
}

impl<T: Copy> Clone for Mat<T> {
    fn clone(&self) -> Mat<T> {
        let n = self.rows * self.cols;

        let mut x = Vec::with_capacity(n);
        unsafe {
            Copy::copy(&self.data, &mut x);
            x.set_len(n);
        }

        Mat::from_vec(self.rows, self.cols, x)
    }
}

impl<T: PartialEq> PartialEq for Mat<T> {
    fn eq(&self, other: &Mat<T>) -> bool {
        self.rows == other.rows &&
        self.cols == other.cols &&
        self.data == other.data
    }
}

impl<T> Index<uint, [T]> for Mat<T> {
    fn index<'a>(&'a self, index: &uint) -> &'a [T] {
        unsafe {
            let ptr = self.data.as_slice().as_ptr().offset((*index * self.cols) as int);
            mem::transmute(Slice { data: ptr, len: self.cols })
        }
    }
}

impl<T: fmt::Show> fmt::Show for Mat<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in range(0u, self.rows) {
            match writeln!(f, "{}", &self[i]) {
                Ok(_) => (),
                x => return x,
            }
        }

        Ok(())
    }
}

#[macro_export]
macro_rules! mat(
    ($([$($e: expr),+]),*) => ({
        // leading _ to allow empty construction without a warning.
        let mut _temp = Mat::new();
        let mut rows = 0u;
        let mut _cols;
        $(
            rows += 1;
            _cols = 0u;
            $(
                _cols += 1;
                _temp.push($e);
            )+
        )*

        unsafe {
            _temp.set_rows(rows);
            _temp.set_cols(_cols);
        }

        _temp
    });
)

#[cfg(test)]
mod tests {
    extern crate test;

    use mat::Mat;

    #[test]
    fn index() {
        let m = mat![[1f32,2f32],[3f32,4f32]];

        assert_eq!(1.0, m[0][0]);
        assert_eq!(2.0, m[0][1]);
        assert_eq!(3.0, m[1][0]);
        assert_eq!(4.0, m[1][1]);
    }
}
<|endoftext|>