<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! A widget for displaying both trees and lists

use gtk;
use gtk::ffi::{mod, FFIWidget};
use gtk::traits;
use gtk::cast::GTK_TREE_VIEW;

/// TreeView — A widget for displaying both trees and lists
struct_Widget!(TreeView)

impl TreeView {
    pub fn new() -> Option<TreeView> {
        let tmp_pointer = unsafe { ffi::gtk_tree_view_new() };
        check_pointer!(tmp_pointer, TreeView)
    }

    pub fn headers_visibles(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_headers_visible(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_header_visibles(&mut self, visibles: bool) {
        unsafe {
            ffi::gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(self.pointer),
                                                   ffi::to_gboolean(visibles))
        }
    }

    pub fn columns_autosize(&mut self) {
        unsafe {
            ffi::gtk_tree_view_columns_autosize(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn headers_clickable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_headers_clickable(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_headers_clickable(&mut self, setting: bool) {
        unsafe {
            ffi::gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(self.pointer),
                                                     ffi::to_gboolean(setting))
        }
    }

    pub fn rules_hint(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_rules_hint(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_rules_hint(&mut self, setting: bool) {
        unsafe {
            ffi::gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(self.pointer),
                                              ffi::to_gboolean(setting))
        }
    }

    #[cfg(any(GTK_3_8, GTK_3_10, GTK_3_12))]
    pub fn activate_on_single_click(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_activate_on_single_click(GTK_TREE_VIEW(self.pointer)))
        }
    }

    #[cfg(any(GTK_3_8, GTK_3_10, GTK_3_12))]
    pub fn set_activate_on_single_click(&mut self, setting: bool) {
        unsafe {
            ffi::gtk_tree_view_set_activate_on_single_click(GTK_TREE_VIEW(self.pointer),
                                                            ffi::to_gboolean(setting))
        }
    }

    #[cfg(any(GTK_3_4, GTK_3_6, GTK_3_8, GTK_3_10, GTK_3_12))]
    pub fn get_n_columns(&self) -> uint {
        unsafe {
            ffi::gtk_tree_view_get_n_columns(GTK_TREE_VIEW(self.pointer)) as uint
        }
    }

    pub fn scroll_to_point(&mut self, tree_x: i32, tree_y: i32) {
        unsafe {
            ffi::gtk_tree_view_scroll_to_point(GTK_TREE_VIEW(self.pointer), tree_x, tree_y)
        }
    }

    pub fn expand_all(&mut self) {
        unsafe {
            ffi::gtk_tree_view_expand_all(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn collapse_all(&mut self) {
        unsafe {
            ffi::gtk_tree_view_collapse_all(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn reorderable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_reorderable(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_reorderable(&mut self, reorderable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_reorderable(GTK_TREE_VIEW(self.pointer),
                                               ffi::to_gboolean(reorderable))
        }
    }

    pub fn unset_rows_drag_source(&mut self) {
        unsafe {
            ffi::gtk_tree_view_unset_rows_drag_source(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn unset_rows_drag_dest(&mut self) {
        unsafe {
            ffi::gtk_tree_view_unset_rows_drag_dest(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn enable_search(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_enable_search(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_enable_search(&mut self, enable_search: bool) {
        unsafe {
            ffi::gtk_tree_view_set_enable_search(GTK_TREE_VIEW(self.pointer),
                                                 ffi::to_gboolean(enable_search))
        }
    }

    pub fn search_column(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_get_search_column(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn set_search_column(&mut self, column: i32) {
        unsafe {
            ffi::gtk_tree_view_set_search_column(GTK_TREE_VIEW(self.pointer), column)
        }
    }

    pub fn search_entry(&self) -> gtk::Entry {
        unsafe {
            ffi::FFIWidget::wrap(ffi::gtk_tree_view_get_search_entry(GTK_TREE_VIEW(self.pointer))
                                 as *mut ffi::C_GtkWidget)
        }
    }

    pub fn set_search_entry(&mut self, entry: &mut gtk::Entry) {
        unsafe {
            ffi::gtk_tree_view_set_search_entry(GTK_TREE_VIEW(self.pointer),
                                                entry.get_widget() as *mut ffi::C_GtkEntry)
        }
    }

    pub fn widget_to_tree_coords(&self, wx: i32, wy: i32) -> (i32, i32) {
        let mut tx = 0i32;
        let mut ty = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             wx, wy, &mut tx, &mut ty);
        }
        (tx, ty)
    }

    pub fn tree_to_widget_coords(&self, tx: i32, ty: i32) -> (i32, i32) {
        let mut wx = 0i32;
        let mut wy = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             tx, ty, &mut wx, &mut wy);
        }
        (wx, wy)
    }

    pub fn widget_to_bin_window_coords(&self, wx: i32, wy: i32) -> (i32, i32) {
        let mut bx = 0i32;
        let mut by = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             wx, wy, &mut bx, &mut by);
        }
        (bx, by)
    }

    pub fn bin_window_to_widget_coords(&self, bx: i32, by: i32) -> (i32, i32) {
        let mut wx = 0i32;
        let mut wy = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             bx, by, &mut wx, &mut wy);
        }
        (wx, wy)
    }

    pub fn tree_to_bin_window_coords(&self, tx: i32, ty: i32) -> (i32, i32) {
        let mut bx = 0i32;
        let mut by = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             tx, ty, &mut bx, &mut by);
        }
        (bx, by)
    }

    pub fn bin_window_to_tree_coords(&self, bx: i32, by: i32) -> (i32, i32) {
        let mut tx = 0i32;
        let mut ty = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             bx, by, &mut tx, &mut ty);
        }
        (tx, ty)
    }

    pub fn fixed_height_mode(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_fixed_height_mode(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_fixed_height_mode(&mut self, enable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(self.pointer),
                                                     ffi::to_gboolean(enable))
        }
    }

    pub fn hover_selection(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_hover_selection(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_hover_selection(&mut self, hover: bool) {
        unsafe {
            ffi::gtk_tree_view_set_hover_selection(GTK_TREE_VIEW(self.pointer),
                                                   ffi::to_gboolean(hover))
        }
    }

    pub fn hover_expand(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_hover_expand(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_hover_expand(&mut self, expand: bool) {
        unsafe {
            ffi::gtk_tree_view_set_hover_expand(GTK_TREE_VIEW(self.pointer),
                                                ffi::to_gboolean(expand))
        }
    }

    pub fn rubber_banding(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_rubber_banding(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_rubber_banding(&mut self, enable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(self.pointer),
                                                  ffi::to_gboolean(enable))
        }
    }

    pub fn is_rubber_banding_active(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_is_rubber_banding_active(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn grid_lines(&self) -> gtk::TreeViewGridLines {
        unsafe {
            ffi::gtk_tree_view_get_grid_lines(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn set_grid_lines(&mut self, grid_lines: gtk::TreeViewGridLines) {
        unsafe {
            ffi::gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(self.pointer), grid_lines)
        }
    }

    pub fn enable_tree_lines(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_enable_tree_lines(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_enable_tree_lines(&mut self, enable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(self.pointer),
                                                     ffi::to_gboolean(enable))
        }
    }

    pub fn show_expanders(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_show_expanders(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_show_expanders(&mut self, enable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(self.pointer),
                                                  ffi::to_gboolean(enable))
        }
    }

    pub fn level_indentation(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_get_level_indentation(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn set_level_indentation(&mut self, indentation: i32) {
        unsafe {
            ffi::gtk_tree_view_set_level_indentation(GTK_TREE_VIEW(self.pointer),
                                                     indentation)
        }
    }

    pub fn tooltip_column(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_get_tooltip_column(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn set_tooltip_column(&mut self, column: i32) {
        unsafe {
            ffi::gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(self.pointer),
                                                  column)
        }
    }
}

impl_drop!(TreeView)
impl_TraitWidget!(TreeView)

impl traits::Container for TreeView {}
impl traits::Scrollable for TreeView {}
<commit_msg>Prepend TreeView getters with 'get_' for consistency<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! A widget for displaying both trees and lists

use gtk;
use gtk::ffi::{mod, FFIWidget};
use gtk::traits;
use gtk::cast::GTK_TREE_VIEW;

/// TreeView — A widget for displaying both trees and lists
struct_Widget!(TreeView)

impl TreeView {
    pub fn new() -> Option<TreeView> {
        let tmp_pointer = unsafe { ffi::gtk_tree_view_new() };
        check_pointer!(tmp_pointer, TreeView)
    }

    pub fn get_headers_visible(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_headers_visible(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_headers_visible(&mut self, visible: bool) {
        unsafe {
            ffi::gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(self.pointer),
                                                   ffi::to_gboolean(visible))
        }
    }

    pub fn columns_autosize(&mut self) {
        unsafe {
            ffi::gtk_tree_view_columns_autosize(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn get_headers_clickable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_headers_clickable(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_headers_clickable(&mut self, setting: bool) {
        unsafe {
            ffi::gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(self.pointer),
                                                     ffi::to_gboolean(setting))
        }
    }

    pub fn get_rules_hint(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_rules_hint(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_rules_hint(&mut self, setting: bool) {
        unsafe {
            ffi::gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(self.pointer),
                                              ffi::to_gboolean(setting))
        }
    }

    #[cfg(any(GTK_3_8, GTK_3_10, GTK_3_12))]
    pub fn get_activate_on_single_click(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_activate_on_single_click(GTK_TREE_VIEW(self.pointer)))
        }
    }

    #[cfg(any(GTK_3_8, GTK_3_10, GTK_3_12))]
    pub fn set_activate_on_single_click(&mut self, setting: bool) {
        unsafe {
            ffi::gtk_tree_view_set_activate_on_single_click(GTK_TREE_VIEW(self.pointer),
                                                            ffi::to_gboolean(setting))
        }
    }

    #[cfg(any(GTK_3_4, GTK_3_6, GTK_3_8, GTK_3_10, GTK_3_12))]
    pub fn get_n_columns(&self) -> uint {
        unsafe {
            ffi::gtk_tree_view_get_n_columns(GTK_TREE_VIEW(self.pointer)) as uint
        }
    }

    pub fn scroll_to_point(&mut self, tree_x: i32, tree_y: i32) {
        unsafe {
            ffi::gtk_tree_view_scroll_to_point(GTK_TREE_VIEW(self.pointer), tree_x, tree_y)
        }
    }

    pub fn expand_all(&mut self) {
        unsafe {
            ffi::gtk_tree_view_expand_all(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn collapse_all(&mut self) {
        unsafe {
            ffi::gtk_tree_view_collapse_all(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn get_reorderable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_reorderable(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_reorderable(&mut self, reorderable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_reorderable(GTK_TREE_VIEW(self.pointer),
                                               ffi::to_gboolean(reorderable))
        }
    }

    pub fn unset_rows_drag_source(&mut self) {
        unsafe {
            ffi::gtk_tree_view_unset_rows_drag_source(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn unset_rows_drag_dest(&mut self) {
        unsafe {
            ffi::gtk_tree_view_unset_rows_drag_dest(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn get_enable_search(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_enable_search(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_enable_search(&mut self, enable_search: bool) {
        unsafe {
            ffi::gtk_tree_view_set_enable_search(GTK_TREE_VIEW(self.pointer),
                                                 ffi::to_gboolean(enable_search))
        }
    }

    pub fn get_search_column(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_get_search_column(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn set_search_column(&mut self, column: i32) {
        unsafe {
            ffi::gtk_tree_view_set_search_column(GTK_TREE_VIEW(self.pointer), column)
        }
    }

    pub fn get_search_entry(&self) -> gtk::Entry {
        unsafe {
            ffi::FFIWidget::wrap(ffi::gtk_tree_view_get_search_entry(GTK_TREE_VIEW(self.pointer))
                                 as *mut ffi::C_GtkWidget)
        }
    }

    pub fn set_search_entry(&mut self, entry: &mut gtk::Entry) {
        unsafe {
            ffi::gtk_tree_view_set_search_entry(GTK_TREE_VIEW(self.pointer),
                                                entry.get_widget() as *mut ffi::C_GtkEntry)
        }
    }

    pub fn widget_to_tree_coords(&self, wx: i32, wy: i32) -> (i32, i32) {
        let mut tx = 0i32;
        let mut ty = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             wx, wy, &mut tx, &mut ty);
        }
        (tx, ty)
    }

    pub fn tree_to_widget_coords(&self, tx: i32, ty: i32) -> (i32, i32) {
        let mut wx = 0i32;
        let mut wy = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             tx, ty, &mut wx, &mut wy);
        }
        (wx, wy)
    }

    pub fn widget_to_bin_window_coords(&self, wx: i32, wy: i32) -> (i32, i32) {
        let mut bx = 0i32;
        let mut by = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             wx, wy, &mut bx, &mut by);
        }
        (bx, by)
    }

    pub fn bin_window_to_widget_coords(&self, bx: i32, by: i32) -> (i32, i32) {
        let mut wx = 0i32;
        let mut wy = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             bx, by, &mut wx, &mut wy);
        }
        (wx, wy)
    }

    pub fn tree_to_bin_window_coords(&self, tx: i32, ty: i32) -> (i32, i32) {
        let mut bx = 0i32;
        let mut by = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             tx, ty, &mut bx, &mut by);
        }
        (bx, by)
    }

    pub fn bin_window_to_tree_coords(&self, bx: i32, by: i32) -> (i32, i32) {
        let mut tx = 0i32;
        let mut ty = 0i32;
        unsafe {
            ffi::gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(self.pointer),
                                                             bx, by, &mut tx, &mut ty);
        }
        (tx, ty)
    }

    pub fn get_fixed_height_mode(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_fixed_height_mode(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_fixed_height_mode(&mut self, enable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(self.pointer),
                                                     ffi::to_gboolean(enable))
        }
    }

    pub fn get_hover_selection(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_hover_selection(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_hover_selection(&mut self, hover: bool) {
        unsafe {
            ffi::gtk_tree_view_set_hover_selection(GTK_TREE_VIEW(self.pointer),
                                                   ffi::to_gboolean(hover))
        }
    }

    pub fn get_hover_expand(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_hover_expand(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_hover_expand(&mut self, expand: bool) {
        unsafe {
            ffi::gtk_tree_view_set_hover_expand(GTK_TREE_VIEW(self.pointer),
                                                ffi::to_gboolean(expand))
        }
    }

    pub fn get_rubber_banding(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_rubber_banding(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_rubber_banding(&mut self, enable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(self.pointer),
                                                  ffi::to_gboolean(enable))
        }
    }

    pub fn is_rubber_banding_active(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_is_rubber_banding_active(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn get_grid_lines(&self) -> gtk::TreeViewGridLines {
        unsafe {
            ffi::gtk_tree_view_get_grid_lines(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn set_grid_lines(&mut self, grid_lines: gtk::TreeViewGridLines) {
        unsafe {
            ffi::gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(self.pointer), grid_lines)
        }
    }

    pub fn get_enable_tree_lines(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_enable_tree_lines(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_enable_tree_lines(&mut self, enable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(self.pointer),
                                                     ffi::to_gboolean(enable))
        }
    }

    pub fn get_show_expanders(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_get_show_expanders(GTK_TREE_VIEW(self.pointer)))
        }
    }

    pub fn set_show_expanders(&mut self, enable: bool) {
        unsafe {
            ffi::gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(self.pointer),
                                                  ffi::to_gboolean(enable))
        }
    }

    pub fn get_level_indentation(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_get_level_indentation(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn set_level_indentation(&mut self, indentation: i32) {
        unsafe {
            ffi::gtk_tree_view_set_level_indentation(GTK_TREE_VIEW(self.pointer),
                                                     indentation)
        }
    }

    pub fn get_tooltip_column(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_get_tooltip_column(GTK_TREE_VIEW(self.pointer))
        }
    }

    pub fn set_tooltip_column(&mut self, column: i32) {
        unsafe {
            ffi::gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(self.pointer),
                                                  column)
        }
    }
}

impl_drop!(TreeView)
impl_TraitWidget!(TreeView)

impl traits::Container for TreeView {}
impl traits::Scrollable for TreeView {}
<|endoftext|>


<commit_before>//! Shader module.
//!
//! Shader functions and declarations can be grouped in so-called *modules*. Modules structure is
//! inherently tied to the filesystem’s tree.
//!
//! You’re not supposed to use modules at the Rust level, even though you can. You’re supposed to
//! actually write modules that will be used by shader programs.

use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

use render::shader::lang::parser;
// FIXME: qualified use, it’s ugly now
use render::shader::lang::syntax::{Declaration, ExternalDeclaration, FunctionDefinition, FullySpecifiedType,
                                   FunctionParameterDeclaration, InitDeclaratorList, Expr,
                                   Module as SyntaxModule, SingleDeclaration, StorageQualifier,
                                   StructSpecifier, StructFieldSpecifier, LayoutQualifier,
                                   TypeSpecifier, TypeQualifier, TypeQualifierSpec, LayoutQualifierSpec};
use sys::resource::{CacheKey, Load, LoadError, LoadResult, Store, StoreKey};

/// Shader module.
///
/// A shader module is a piece of GLSL code with optional import lists (dependencies).
///
/// You’re not supposed to directly manipulate any object of this type. You just write modules on
/// disk and let everyting happen automatically for you.
#[derive(Clone, Debug, PartialEq)]
pub struct Module(pub SyntaxModule); // FIXME: remove the pub

impl Module {
  /// Retrieve all the modules this module depends on, without duplicates.
  pub fn deps(&self, store: &mut Store, key: &ModuleKey) -> Result<Vec<ModuleKey>, DepsError> {
    let mut deps = Vec::new();
    self.deps_no_cycle(store, &key, &mut Vec::new(), &mut deps).map(|_| deps)
  }

  fn deps_no_cycle(&self, store: &mut Store, key: &ModuleKey, parents: &mut Vec<ModuleKey>, deps: &mut Vec<ModuleKey>) -> Result<(), DepsError> {
    let imports = self.0.imports.iter().map(|il| &il.module);

    parents.push(key.clone());

    for module_path in imports {
      let module_key = ModuleKey(module_path.path.join("."));

      // check whether it’s already in the deps
      if deps.contains(&module_key) {
        continue;
      }

      // check whether the module was already visited
      if parents.contains(&module_key) {
        return Err(DepsError::Cycle(module_key.clone(), module_key.clone()));
      }

      // get the dependency module
      let module = store.get(&module_key).ok_or_else(|| DepsError::LoadError(module_key.clone()))?;
      module.borrow().deps_no_cycle(store, &module_key, parents, deps)?;

      deps.push(module_key.clone());
      parents.pop();
    }

    Ok(())
  }

  /// Fold a module and its dependencies into a single module. The list of dependencies is also
  /// returned.
  pub fn gather(&self, store: &mut Store, k: &ModuleKey) -> Result<(Self, Vec<ModuleKey>), DepsError> {
    let deps = self.deps(store, k)?;
    let glsl =
      deps.iter()
          .flat_map(|kd| {
              let m = store.get(kd).unwrap();
              let g = m.borrow().0.glsl.clone();
              g
            })
          .chain(self.0.glsl.clone())
          .collect();

    let module = Module(SyntaxModule {
      imports: Vec::new(),
      glsl
    });

    Ok((module, deps))
  }

  /// Get all the uniforms defined in a module.
  pub fn uniforms(&self) -> Vec<SingleDeclaration> {
    let mut uniforms = Vec::new();

    for glsl in &self.0.glsl {
      if let ExternalDeclaration::Declaration(Declaration::InitDeclaratorList(ref i)) = *glsl {
        if let Some(ref q) = i.head.ty.qualifier {
          if q.qualifiers.contains(&TypeQualifierSpec::Storage(StorageQualifier::Uniform)) {
            uniforms.push(i.head.clone());

            // check whether we have more
            for next in &i.tail {
              uniforms.push(SingleDeclaration {
                ty: i.head.ty.clone(),
                name: Some(next.name.clone()),
                array_specifier: next.array_specifier.clone(),
                initializer: None
              })
            }
          }
        }
      }
    }

    uniforms
  }

  /// Get all the functions.
  pub fn functions(&self) -> Vec<FunctionDefinition> {
    self.0.glsl.iter().filter_map(|ed| match *ed {
      ExternalDeclaration::FunctionDefinition(ref def) => Some(def.clone()),
      _ => None
    }).collect()
  }

  /// Get all the declared structures.
  pub fn structs(&self) -> Vec<StructSpecifier> {
    self.0.glsl.iter().filter_map(|ed| {
      match *ed {
        ExternalDeclaration::Declaration(
          Declaration::InitDeclaratorList(
            InitDeclaratorList {
              head: SingleDeclaration {
                ty: FullySpecifiedType {
                  ty: TypeSpecifier::Struct(ref s),
                  ..
                },
                ..
              },
              ..
            }
          )
        ) => Some(s.clone()),
        _ => None
      }
    }).collect()
  }
}

/// Vertex shader I/O interface.
///
/// It contains the inputs and the outputs to the next stage.
#[derive(Clone, Debug, PartialEq)]
pub struct VertexShaderInterface {
  inputs: Vec<ExternalDeclaration>,
  outputs: Vec<ExternalDeclaration>
}

#[derive(Clone, Debug, PartialEq)]
pub enum VertexShaderInterfaceError {
  UnnamedInput,
  OutputHasMainQualifier,
  OutputTypeMustBeAStruct(TypeSpecifier),
  WrongOutputFirstField(StructFieldSpecifier),
  OutputFieldCannotBeStruct(usize, TypeSpecifier),
  OutputFieldCannotHaveSeveralIdentifiers(usize, StructFieldSpecifier)
}

/// Build the vertex shader interface from a function definition.
pub fn vertex_shader_interface(fun_def: &FunctionDefinition, structs: &[StructSpecifier]) -> Result<VertexShaderInterface, VertexShaderInterfaceError> {
  let proto = &fun_def.prototype;
  let inputs = vertex_shader_inputs(proto.parameters.iter())?;
  let outputs = vertex_shader_outputs(&proto.ty, structs)?;

  Ok(VertexShaderInterface { inputs, outputs })
}

fn vertex_shader_inputs<'a, I>(args: I) -> Result<Vec<ExternalDeclaration>, VertexShaderInterfaceError> where I: IntoIterator<Item = &'a FunctionParameterDeclaration> {
  let mut inputs = Vec::new();

  for (i, arg) in args.into_iter().enumerate() {
    match *arg {
      FunctionParameterDeclaration::Unnamed(..) => return Err(VertexShaderInterfaceError::UnnamedInput),
      FunctionParameterDeclaration::Named(ref ty_qual, ref decl) => {
        let layout_qualifier = LayoutQualifier {
          ids: vec![LayoutQualifierSpec::Identifier("location".to_owned(), Some(Box::new(Expr::IntConst(i as i32))))]
        };
        let base_qualifier = TypeQualifier {
          qualifiers: vec![
            TypeQualifierSpec::Layout(layout_qualifier),
            TypeQualifierSpec::Storage(StorageQualifier::Uniform)
          ]
        };
        let qualifier = match *ty_qual {
          Some(ref qual) => TypeQualifier { qualifiers: base_qualifier.qualifiers.into_iter().chain(qual.clone().qualifiers).collect() },
          None => base_qualifier
        };
        let ty = decl.ty.clone();
        let name = Some(decl.name.clone());
        let array_spec = decl.array_spec.clone();
        let idl = InitDeclaratorList {
          head: SingleDeclaration {
            ty: FullySpecifiedType {
              qualifier: Some(qualifier),
              ty
            },
            name,
            array_specifier: array_spec,
            initializer: None
          },
          tail: Vec::new()
        };
        let ed = ExternalDeclaration::Declaration(Declaration::InitDeclaratorList(idl));

        inputs.push(ed);
      }
    }
  }

  Ok(inputs)
}

fn vertex_shader_outputs(fsty: &FullySpecifiedType, structs: &[StructSpecifier]) -> Result<Vec<ExternalDeclaration>, VertexShaderInterfaceError> {
  // we refuse that the output has a main qualifier
  if fsty.qualifier.is_some() {
    return Err(VertexShaderInterfaceError::OutputHasMainQualifier);
  }

  let ty = &fsty.ty;

  // we enforce that the output must be a struct that follows a certain pattern
  match *ty {
    TypeSpecifier::TypeName(ref ty_name) => {
      let real_ty = structs.iter().find(|ref s| s.name.as_ref() == Some(ty_name));

      match real_ty {
        Some(ref s) => {
          // the first field must be named "gl_Position", has type vec4 and no qualifier
          let first_field = &s.fields[0];

          if first_field.qualifier.is_some() ||
             first_field.ty != TypeSpecifier::Vec4 ||
             first_field.identifiers != vec![("gl_Position".to_owned(), None)] {
            return Err(VertexShaderInterfaceError::WrongOutputFirstField(first_field.clone()));
          }

          // then, for all other fields, we check that they are not composite type (i.e. structs); if
          // they are not, add them to the interface; otherwise, fail
          let mut outputs = Vec::new();

          for (i, field) in (&s.fields[1..]).into_iter().enumerate() {
            if let TypeSpecifier::Struct(_) = field.ty {
              return Err(VertexShaderInterfaceError::OutputFieldCannotBeStruct(i, field.ty.clone()));
            }

            if field.identifiers.len() > 1 {
              return Err(VertexShaderInterfaceError::OutputFieldCannotHaveSeveralIdentifiers(i, field.clone()));
            }

            outputs.push(vertex_shader_output_field_to_ext_decl(&field));
          }

          Ok(outputs)
        }
        _ => Err(VertexShaderInterfaceError::OutputTypeMustBeAStruct(ty.clone()))
      }
    }
    _ => Err(VertexShaderInterfaceError::OutputTypeMustBeAStruct(ty.clone()))
  }
}

fn vertex_shader_output_field_to_ext_decl(field: &StructFieldSpecifier) -> ExternalDeclaration {
  let fsty = FullySpecifiedType {
    qualifier: field.qualifier.clone(),
    ty: field.ty.clone()
  };
  let decl = SingleDeclaration {
    ty: fsty,
    name: Some(field.identifiers[0].0.clone()),
    array_specifier: field.identifiers[0].1.clone(),
    initializer: None
  };

  ExternalDeclaration::Declaration(
    Declaration::InitDeclaratorList(
      InitDeclaratorList {
        head: decl,
        tail: Vec::new()
      }
    )
  )
}

/// Class of errors that can happen in dependencies.
#[derive(Clone, Debug, PartialEq)]
pub enum DepsError {
  /// If a module’s dependencies has any cycle, the dependencies are unusable and the cycle is
  /// returned.
  Cycle(ModuleKey, ModuleKey),
  /// There was a loading error of a module.
  LoadError(ModuleKey)
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ModuleKey(String);

impl ModuleKey {
  pub fn new(key: &str) -> Self {
    ModuleKey(key.to_owned())
  }
}

impl CacheKey for ModuleKey {
  type Target = Module;
}

impl StoreKey for ModuleKey {
  fn key_to_path(&self) -> PathBuf {
    PathBuf::from(self.0.replace(".", "/") + ".spsl")
  }
}

impl Load for Module {
  fn load<K>(key: &K, _: &mut Store) -> Result<LoadResult<Self>, LoadError> where K: StoreKey<Target = Self> {
    let path = key.key_to_path();

    let mut fh = File::open(&path).map_err(|_| LoadError::FileNotFound(path.into()))?;
    let mut src = String::new();
    let _ = fh.read_to_string(&mut src);

    match parser::parse_str(&src[..], parser::module) {
      parser::ParseResult::Ok(module) => {
        Ok(Module(module).into())
      }
      parser::ParseResult::Err(e) => Err(LoadError::ConversionFailed(format!("{:?}", e))),
      _ => Err(LoadError::ConversionFailed("incomplete input".to_owned()))
    }
  }
}

<commit_msg>Am I drunk or what?<commit_after>//! Shader module.
//!
//! Shader functions and declarations can be grouped in so-called *modules*. Modules structure is
//! inherently tied to the filesystem’s tree.
//!
//! You’re not supposed to use modules at the Rust level, even though you can. You’re supposed to
//! actually write modules that will be used by shader programs.

use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

use render::shader::lang::parser;
// FIXME: qualified use, it’s ugly now
use render::shader::lang::syntax::{Declaration, ExternalDeclaration, FunctionDefinition, FullySpecifiedType,
                                   FunctionParameterDeclaration, InitDeclaratorList, Expr,
                                   Module as SyntaxModule, SingleDeclaration, StorageQualifier,
                                   StructSpecifier, StructFieldSpecifier, LayoutQualifier,
                                   TypeSpecifier, TypeQualifier, TypeQualifierSpec, LayoutQualifierSpec};
use sys::resource::{CacheKey, Load, LoadError, LoadResult, Store, StoreKey};

/// Shader module.
///
/// A shader module is a piece of GLSL code with optional import lists (dependencies).
///
/// You’re not supposed to directly manipulate any object of this type. You just write modules on
/// disk and let everyting happen automatically for you.
#[derive(Clone, Debug, PartialEq)]
pub struct Module(pub SyntaxModule); // FIXME: remove the pub

impl Module {
  /// Retrieve all the modules this module depends on, without duplicates.
  pub fn deps(&self, store: &mut Store, key: &ModuleKey) -> Result<Vec<ModuleKey>, DepsError> {
    let mut deps = Vec::new();
    self.deps_no_cycle(store, &key, &mut Vec::new(), &mut deps).map(|_| deps)
  }

  fn deps_no_cycle(&self, store: &mut Store, key: &ModuleKey, parents: &mut Vec<ModuleKey>, deps: &mut Vec<ModuleKey>) -> Result<(), DepsError> {
    let imports = self.0.imports.iter().map(|il| &il.module);

    parents.push(key.clone());

    for module_path in imports {
      let module_key = ModuleKey(module_path.path.join("."));

      // check whether it’s already in the deps
      if deps.contains(&module_key) {
        continue;
      }

      // check whether the module was already visited
      if parents.contains(&module_key) {
        return Err(DepsError::Cycle(module_key.clone(), module_key.clone()));
      }

      // get the dependency module
      let module = store.get(&module_key).ok_or_else(|| DepsError::LoadError(module_key.clone()))?;
      module.borrow().deps_no_cycle(store, &module_key, parents, deps)?;

      deps.push(module_key.clone());
      parents.pop();
    }

    Ok(())
  }

  /// Fold a module and its dependencies into a single module. The list of dependencies is also
  /// returned.
  pub fn gather(&self, store: &mut Store, k: &ModuleKey) -> Result<(Self, Vec<ModuleKey>), DepsError> {
    let deps = self.deps(store, k)?;
    let glsl =
      deps.iter()
          .flat_map(|kd| {
              let m = store.get(kd).unwrap();
              let g = m.borrow().0.glsl.clone();
              g
            })
          .chain(self.0.glsl.clone())
          .collect();

    let module = Module(SyntaxModule {
      imports: Vec::new(),
      glsl
    });

    Ok((module, deps))
  }

  /// Get all the uniforms defined in a module.
  pub fn uniforms(&self) -> Vec<SingleDeclaration> {
    let mut uniforms = Vec::new();

    for glsl in &self.0.glsl {
      if let ExternalDeclaration::Declaration(Declaration::InitDeclaratorList(ref i)) = *glsl {
        if let Some(ref q) = i.head.ty.qualifier {
          if q.qualifiers.contains(&TypeQualifierSpec::Storage(StorageQualifier::Uniform)) {
            uniforms.push(i.head.clone());

            // check whether we have more
            for next in &i.tail {
              uniforms.push(SingleDeclaration {
                ty: i.head.ty.clone(),
                name: Some(next.name.clone()),
                array_specifier: next.array_specifier.clone(),
                initializer: None
              })
            }
          }
        }
      }
    }

    uniforms
  }

  /// Get all the functions.
  pub fn functions(&self) -> Vec<FunctionDefinition> {
    self.0.glsl.iter().filter_map(|ed| match *ed {
      ExternalDeclaration::FunctionDefinition(ref def) => Some(def.clone()),
      _ => None
    }).collect()
  }

  /// Get all the declared structures.
  pub fn structs(&self) -> Vec<StructSpecifier> {
    self.0.glsl.iter().filter_map(|ed| {
      match *ed {
        ExternalDeclaration::Declaration(
          Declaration::InitDeclaratorList(
            InitDeclaratorList {
              head: SingleDeclaration {
                ty: FullySpecifiedType {
                  ty: TypeSpecifier::Struct(ref s),
                  ..
                },
                ..
              },
              ..
            }
          )
        ) => Some(s.clone()),
        _ => None
      }
    }).collect()
  }
}

/// Vertex shader I/O interface.
///
/// It contains the inputs and the outputs to the next stage.
#[derive(Clone, Debug, PartialEq)]
pub struct VertexShaderInterface {
  inputs: Vec<ExternalDeclaration>,
  outputs: Vec<ExternalDeclaration>
}

#[derive(Clone, Debug, PartialEq)]
pub enum VertexShaderInterfaceError {
  UnnamedInput,
  OutputHasMainQualifier,
  OutputTypeMustBeAStruct(TypeSpecifier),
  WrongOutputFirstField(StructFieldSpecifier),
  OutputFieldCannotBeStruct(usize, TypeSpecifier),
  OutputFieldCannotHaveSeveralIdentifiers(usize, StructFieldSpecifier)
}

/// Build the vertex shader interface from a function definition.
pub fn vertex_shader_interface(fun_def: &FunctionDefinition, structs: &[StructSpecifier]) -> Result<VertexShaderInterface, VertexShaderInterfaceError> {
  let proto = &fun_def.prototype;
  let inputs = vertex_shader_inputs(proto.parameters.iter())?;
  let outputs = vertex_shader_outputs(&proto.ty, structs)?;

  Ok(VertexShaderInterface { inputs, outputs })
}

fn vertex_shader_inputs<'a, I>(args: I) -> Result<Vec<ExternalDeclaration>, VertexShaderInterfaceError> where I: IntoIterator<Item = &'a FunctionParameterDeclaration> {
  let mut inputs = Vec::new();

  for (i, arg) in args.into_iter().enumerate() {
    match *arg {
      FunctionParameterDeclaration::Unnamed(..) => return Err(VertexShaderInterfaceError::UnnamedInput),
      FunctionParameterDeclaration::Named(ref ty_qual, ref decl) => {
        let layout_qualifier = LayoutQualifier {
          ids: vec![LayoutQualifierSpec::Identifier("location".to_owned(), Some(Box::new(Expr::IntConst(i as i32))))]
        };
        let base_qualifier = TypeQualifier {
          qualifiers: vec![
            TypeQualifierSpec::Layout(layout_qualifier),
            TypeQualifierSpec::Storage(StorageQualifier::In)
          ]
        };
        let qualifier = match *ty_qual {
          Some(ref qual) => TypeQualifier { qualifiers: base_qualifier.qualifiers.into_iter().chain(qual.clone().qualifiers).collect() },
          None => base_qualifier
        };
        let ty = decl.ty.clone();
        let name = Some(decl.name.clone());
        let array_spec = decl.array_spec.clone();
        let idl = InitDeclaratorList {
          head: SingleDeclaration {
            ty: FullySpecifiedType {
              qualifier: Some(qualifier),
              ty
            },
            name,
            array_specifier: array_spec,
            initializer: None
          },
          tail: Vec::new()
        };
        let ed = ExternalDeclaration::Declaration(Declaration::InitDeclaratorList(idl));

        inputs.push(ed);
      }
    }
  }

  Ok(inputs)
}

fn vertex_shader_outputs(fsty: &FullySpecifiedType, structs: &[StructSpecifier]) -> Result<Vec<ExternalDeclaration>, VertexShaderInterfaceError> {
  // we refuse that the output has a main qualifier
  if fsty.qualifier.is_some() {
    return Err(VertexShaderInterfaceError::OutputHasMainQualifier);
  }

  let ty = &fsty.ty;

  // we enforce that the output must be a struct that follows a certain pattern
  match *ty {
    TypeSpecifier::TypeName(ref ty_name) => {
      let real_ty = structs.iter().find(|ref s| s.name.as_ref() == Some(ty_name));

      match real_ty {
        Some(ref s) => {
          // the first field must be named "gl_Position", has type vec4 and no qualifier
          let first_field = &s.fields[0];

          if first_field.qualifier.is_some() ||
             first_field.ty != TypeSpecifier::Vec4 ||
             first_field.identifiers != vec![("gl_Position".to_owned(), None)] {
            return Err(VertexShaderInterfaceError::WrongOutputFirstField(first_field.clone()));
          }

          // then, for all other fields, we check that they are not composite type (i.e. structs); if
          // they are not, add them to the interface; otherwise, fail
          let mut outputs = Vec::new();

          for (i, field) in (&s.fields[1..]).into_iter().enumerate() {
            if let TypeSpecifier::Struct(_) = field.ty {
              return Err(VertexShaderInterfaceError::OutputFieldCannotBeStruct(i, field.ty.clone()));
            }

            if field.identifiers.len() > 1 {
              return Err(VertexShaderInterfaceError::OutputFieldCannotHaveSeveralIdentifiers(i, field.clone()));
            }

            outputs.push(vertex_shader_output_field_to_ext_decl(&field));
          }

          Ok(outputs)
        }
        _ => Err(VertexShaderInterfaceError::OutputTypeMustBeAStruct(ty.clone()))
      }
    }
    _ => Err(VertexShaderInterfaceError::OutputTypeMustBeAStruct(ty.clone()))
  }
}

fn vertex_shader_output_field_to_ext_decl(field: &StructFieldSpecifier) -> ExternalDeclaration {
  let fsty = FullySpecifiedType {
    qualifier: field.qualifier.clone(),
    ty: field.ty.clone()
  };
  let decl = SingleDeclaration {
    ty: fsty,
    name: Some(field.identifiers[0].0.clone()),
    array_specifier: field.identifiers[0].1.clone(),
    initializer: None
  };

  ExternalDeclaration::Declaration(
    Declaration::InitDeclaratorList(
      InitDeclaratorList {
        head: decl,
        tail: Vec::new()
      }
    )
  )
}

/// Class of errors that can happen in dependencies.
#[derive(Clone, Debug, PartialEq)]
pub enum DepsError {
  /// If a module’s dependencies has any cycle, the dependencies are unusable and the cycle is
  /// returned.
  Cycle(ModuleKey, ModuleKey),
  /// There was a loading error of a module.
  LoadError(ModuleKey)
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ModuleKey(String);

impl ModuleKey {
  pub fn new(key: &str) -> Self {
    ModuleKey(key.to_owned())
  }
}

impl CacheKey for ModuleKey {
  type Target = Module;
}

impl StoreKey for ModuleKey {
  fn key_to_path(&self) -> PathBuf {
    PathBuf::from(self.0.replace(".", "/") + ".spsl")
  }
}

impl Load for Module {
  fn load<K>(key: &K, _: &mut Store) -> Result<LoadResult<Self>, LoadError> where K: StoreKey<Target = Self> {
    let path = key.key_to_path();

    let mut fh = File::open(&path).map_err(|_| LoadError::FileNotFound(path.into()))?;
    let mut src = String::new();
    let _ = fh.read_to_string(&mut src);

    match parser::parse_str(&src[..], parser::module) {
      parser::ParseResult::Ok(module) => {
        Ok(Module(module).into())
      }
      parser::ParseResult::Err(e) => Err(LoadError::ConversionFailed(format!("{:?}", e))),
      _ => Err(LoadError::ConversionFailed("incomplete input".to_owned()))
    }
  }
}

<|endoftext|>


<commit_before>use std::io::{Stream, IoResult, OtherIoError, IoError};
use client::request::RequestWriter;
use rfc2616::{CR, LF, SP};
use common::read_http_version;
use headers;
use status::Status;

use buffer::BufferedStream;
use server::request::{RequestBuffer};
use headers::{EndOfFile, EndOfHeaders, MalformedHeaderSyntax, MalformedHeaderValue};

pub struct ResponseReader<S> {
    stream: BufferedStream<S>,

    /// The request which this is a response to
    pub request: RequestWriter<S>,

    /// The HTTP version number; typically `(1, 1)` or, less commonly, `(1, 0)`.
    pub version: (uint, uint),

    /// The HTTP status indicated in the response.
    pub status: Status,

    /// The headers received in the response.
    pub headers: Box<headers::response::HeaderCollection>,
}

fn bad_response_err() -> IoError {
    // TODO: IoError isn't right
    IoError {
        kind: OtherIoError,
        desc: "Server returned malformed HTTP response",
        detail: None,
    }
}

impl<S: Stream> ResponseReader<S> {
    pub fn construct(mut stream: BufferedStream<S>, request: RequestWriter<S>)
            -> Result<ResponseReader<S>, (RequestWriter<S>, IoError)> {
        // TODO: raise condition at the points where Err is returned
        //let mut b = [0u8, ..4096];
        //let len = stream.read(b);
        //println!("{}", ::std::str::from_bytes(b.slice_to(len.unwrap())));
        let http_version = match read_http_version(&mut stream, |b| b == SP) {
            Ok(nums) => nums,
            Err(_) => return Err((request, bad_response_err())),
        };

        // Read the status code
        let mut digits = 0u8;
        let mut status_code = 0u16;
        loop {
            if digits == 4u8 {
                // Status code must be three digits long
                return Err((request, bad_response_err()));
            }
            match stream.read_byte() {
                Ok(b) if b >= b'0' && b <= b'9' => {
                    status_code = status_code * 10 + b as u16 - '0' as u16;
                },
                Ok(b) if b == SP => break,
                _ => return Err((request, bad_response_err())),
            }
            digits += 1;
        }

        // Read the status reason
        let mut reason = String::new();
        loop {
            match stream.read_byte() {
                Ok(b) if b == CR => {
                    if stream.read_byte() == Ok(LF) {
                        break;
                    } else {
                        // Response-Line has CR without LF. Not yet resilient; TODO.
                        return Err((request, bad_response_err()));
                    }
                }
                Ok(b) => {
                    reason.push_char(b as char);
                }
                Err(_) => return Err((request, bad_response_err())),
            }
        }

        // Now we sneakily slip back to server::RequestBuffer to avoid code duplication. This is
        // temporary, honest!
        //
        // You see, read_header and read_header_line will be replaced, as will this. The code will
        // not be shared between them as they will have ultra-smart parsers (probably using Ragel)
        // to provide fast loading of standard headers, and the set of defined headers is distinct
        // between a request and response.
        let headers = {
            let mut buffer = RequestBuffer::new(&mut stream);
            let mut headers = box headers::response::HeaderCollection::new();
            loop {
                let xxx = buffer.read_header::<headers::response::Header>();
                info!("header = {:?}", xxx);
                match xxx {
                //match buffer.read_header::<headers::response::Header>() {
                    Err(EndOfFile) => {
                        //fail!("server disconnected, no more response to receive :-(");
                        return Err((request, bad_response_err()));
                    },
                    Err(EndOfHeaders) => break,
                    Err(MalformedHeaderSyntax) => {
                        return Err((request, bad_response_err()));
                    },
                    Err(MalformedHeaderValue) => {
                        println!("Bad header encountered. TODO: handle this better.");
                        // Now just ignore the header
                    },
                    Ok(header) => {
                        headers.insert(header);
                    },
                }
            }
            headers
        };

        Ok(ResponseReader {
            stream: stream,
            request: request,
            version: http_version,
            status: Status::from_code_and_reason(status_code, reason),
            headers: headers,
        })
    }
}

impl<S: Stream> Reader for ResponseReader<S> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.stream.read(buf)
    }
}
<commit_msg>Unbox client Response::headers.<commit_after>use std::io::{Stream, IoResult, OtherIoError, IoError};
use client::request::RequestWriter;
use rfc2616::{CR, LF, SP};
use common::read_http_version;
use headers;
use status::Status;

use buffer::BufferedStream;
use server::request::{RequestBuffer};
use headers::{EndOfFile, EndOfHeaders, MalformedHeaderSyntax, MalformedHeaderValue};

pub struct ResponseReader<S> {
    stream: BufferedStream<S>,

    /// The request which this is a response to
    pub request: RequestWriter<S>,

    /// The HTTP version number; typically `(1, 1)` or, less commonly, `(1, 0)`.
    pub version: (uint, uint),

    /// The HTTP status indicated in the response.
    pub status: Status,

    /// The headers received in the response.
    pub headers: headers::response::HeaderCollection,
}

fn bad_response_err() -> IoError {
    // TODO: IoError isn't right
    IoError {
        kind: OtherIoError,
        desc: "Server returned malformed HTTP response",
        detail: None,
    }
}

impl<S: Stream> ResponseReader<S> {
    pub fn construct(mut stream: BufferedStream<S>, request: RequestWriter<S>)
            -> Result<ResponseReader<S>, (RequestWriter<S>, IoError)> {
        // TODO: raise condition at the points where Err is returned
        //let mut b = [0u8, ..4096];
        //let len = stream.read(b);
        //println!("{}", ::std::str::from_bytes(b.slice_to(len.unwrap())));
        let http_version = match read_http_version(&mut stream, |b| b == SP) {
            Ok(nums) => nums,
            Err(_) => return Err((request, bad_response_err())),
        };

        // Read the status code
        let mut digits = 0u8;
        let mut status_code = 0u16;
        loop {
            if digits == 4u8 {
                // Status code must be three digits long
                return Err((request, bad_response_err()));
            }
            match stream.read_byte() {
                Ok(b) if b >= b'0' && b <= b'9' => {
                    status_code = status_code * 10 + b as u16 - '0' as u16;
                },
                Ok(b) if b == SP => break,
                _ => return Err((request, bad_response_err())),
            }
            digits += 1;
        }

        // Read the status reason
        let mut reason = String::new();
        loop {
            match stream.read_byte() {
                Ok(b) if b == CR => {
                    if stream.read_byte() == Ok(LF) {
                        break;
                    } else {
                        // Response-Line has CR without LF. Not yet resilient; TODO.
                        return Err((request, bad_response_err()));
                    }
                }
                Ok(b) => {
                    reason.push_char(b as char);
                }
                Err(_) => return Err((request, bad_response_err())),
            }
        }

        // Now we sneakily slip back to server::RequestBuffer to avoid code duplication. This is
        // temporary, honest!
        //
        // You see, read_header and read_header_line will be replaced, as will this. The code will
        // not be shared between them as they will have ultra-smart parsers (probably using Ragel)
        // to provide fast loading of standard headers, and the set of defined headers is distinct
        // between a request and response.
        let headers = {
            let mut buffer = RequestBuffer::new(&mut stream);
            let mut headers = headers::response::HeaderCollection::new();
            loop {
                let xxx = buffer.read_header::<headers::response::Header>();
                info!("header = {:?}", xxx);
                match xxx {
                //match buffer.read_header::<headers::response::Header>() {
                    Err(EndOfFile) => {
                        //fail!("server disconnected, no more response to receive :-(");
                        return Err((request, bad_response_err()));
                    },
                    Err(EndOfHeaders) => break,
                    Err(MalformedHeaderSyntax) => {
                        return Err((request, bad_response_err()));
                    },
                    Err(MalformedHeaderValue) => {
                        println!("Bad header encountered. TODO: handle this better.");
                        // Now just ignore the header
                    },
                    Ok(header) => {
                        headers.insert(header);
                    },
                }
            }
            headers
        };

        Ok(ResponseReader {
            stream: stream,
            request: request,
            version: http_version,
            status: Status::from_code_and_reason(status_code, reason),
            headers: headers,
        })
    }
}

impl<S: Stream> Reader for ResponseReader<S> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.stream.read(buf)
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use infer::outlives::env::RegionBoundPairs;
use infer::{GenericKind, VerifyBound};
use traits;
use ty::subst::{Subst, Substs};
use ty::{self, Ty, TyCtxt};

/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
/// obligation into a series of `'a: 'b` constraints and "verifys", as
/// described on the module comment. The final constraints are emitted
/// via a "delegate" of type `D` -- this is usually the `infcx`, which
/// accrues them into the `region_obligations` code, but for NLL we
/// use something else.
pub struct VerifyBoundCx<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
    region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
    implicit_region_bound: Option<ty::Region<'tcx>>,
    param_env: ty::ParamEnv<'tcx>,
}

impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
    pub fn new(
        tcx: TyCtxt<'cx, 'gcx, 'tcx>,
        region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
        implicit_region_bound: Option<ty::Region<'tcx>>,
        param_env: ty::ParamEnv<'tcx>,
    ) -> Self {
        Self {
            tcx,
            region_bound_pairs,
            implicit_region_bound,
            param_env,
        }
    }

    /// Returns a "verify bound" that encodes what we know about
    /// `generic` and the regions it outlives.
    pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
        match generic {
            GenericKind::Param(param_ty) => self.param_bound(param_ty),
            GenericKind::Projection(projection_ty) => self.projection_bound(projection_ty),
        }
    }

    fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
        match ty.sty {
            ty::Param(p) => self.param_bound(p),
            ty::Projection(data) => self.projection_bound(data),
            _ => self.recursive_type_bound(ty),
        }
    }

    fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
        debug!("param_bound(param_ty={:?})", param_ty);

        let mut param_bounds = self.declared_generic_bounds_from_env(GenericKind::Param(param_ty));

        // Add in the default bound of fn body that applies to all in
        // scope type parameters:
        param_bounds.extend(self.implicit_region_bound);

        VerifyBound::AnyRegion(param_bounds)
    }

    /// Given a projection like `T::Item`, searches the environment
    /// for where-clauses like `T::Item: 'a`. Returns the set of
    /// regions `'a` that it finds.  This is a "conservative" check --
    /// it may not find all applicable bounds, but all the bounds it
    /// returns can be relied upon.
    pub fn projection_declared_bounds_from_env(
        &self,
        projection_ty: ty::ProjectionTy<'tcx>,
    ) -> Vec<ty::Region<'tcx>> {
        self.declared_generic_bounds_from_env(GenericKind::Projection(projection_ty))
    }

    /// Searches the where clauses in scope for regions that
    /// `projection_ty` is known to outlive. Currently requires an
    /// exact match.
    pub fn projection_declared_bounds_from_trait(
        &self,
        projection_ty: ty::ProjectionTy<'tcx>,
    ) -> Vec<ty::Region<'tcx>> {
        self.declared_projection_bounds_from_trait(projection_ty)
    }

    pub fn projection_bound(
        &self,
        projection_ty: ty::ProjectionTy<'tcx>,
    ) -> VerifyBound<'tcx> {
        debug!(
            "projection_bound(projection_ty={:?})",
            projection_ty
        );

        let mut declared_bounds =
            self.projection_declared_bounds_from_env(projection_ty);

        declared_bounds.extend(
            self.projection_declared_bounds_from_trait(projection_ty)
        );

        debug!("projection_bound: declared_bounds = {:?}", declared_bounds);

        // see the extensive comment in projection_must_outlive
        let ty = self.tcx
            .mk_projection(projection_ty.item_def_id, projection_ty.substs);
        let recursive_bound = self.recursive_type_bound(ty);

        VerifyBound::AnyRegion(declared_bounds).or(recursive_bound)
    }

    fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
        let mut bounds = ty.walk_shallow()
            .map(|subty| self.type_bound(subty))
            .collect::<Vec<_>>();

        let mut regions = ty.regions();
        regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
        bounds.push(VerifyBound::AllRegions(regions));

        // remove bounds that must hold, since they are not interesting
        bounds.retain(|b| !b.must_hold());

        if bounds.len() == 1 {
            bounds.pop().unwrap()
        } else {
            VerifyBound::AllBounds(bounds)
        }
    }

    fn declared_generic_bounds_from_env(
        &self,
        generic: GenericKind<'tcx>,
    ) -> Vec<ty::Region<'tcx>> {
        let tcx = self.tcx;

        // To start, collect bounds from user environment. Note that
        // parameter environments are already elaborated, so we don't
        // have to worry about that. Comparing using `==` is a bit
        // dubious for projections, but it will work for simple cases
        // like `T` and `T::Item`. It may not work as well for things
        // like `<T as Foo<'a>>::Item`.
        let generic_ty = generic.to_ty(tcx);
        let c_b = self.param_env.caller_bounds;
        let mut param_bounds = self.collect_outlives_from_predicate_list(generic_ty, c_b);

        // Next, collect regions we scraped from the well-formedness
        // constraints in the fn signature. To do that, we walk the list
        // of known relations from the fn ctxt.
        //
        // This is crucial because otherwise code like this fails:
        //
        //     fn foo<'a, A>(x: &'a A) { x.bar() }
        //
        // The problem is that the type of `x` is `&'a A`. To be
        // well-formed, then, A must be lower-generic by `'a`, but we
        // don't know that this holds from first principles.
        for &(r, p) in self.region_bound_pairs {
            debug!("generic={:?} p={:?}", generic, p);
            if generic == p {
                param_bounds.push(r);
            }
        }

        param_bounds
    }

    /// Given a projection like `<T as Foo<'x>>::Bar`, returns any bounds
    /// declared in the trait definition. For example, if the trait were
    ///
    /// ```rust
    /// trait Foo<'a> {
    ///     type Bar: 'a;
    /// }
    /// ```
    ///
    /// then this function would return `'x`. This is subject to the
    /// limitations around higher-ranked bounds described in
    /// `region_bounds_declared_on_associated_item`.
    fn declared_projection_bounds_from_trait(
        &self,
        projection_ty: ty::ProjectionTy<'tcx>,
    ) -> Vec<ty::Region<'tcx>> {
        debug!("projection_bounds(projection_ty={:?})", projection_ty);
        let mut bounds = self.region_bounds_declared_on_associated_item(projection_ty.item_def_id);
        for r in &mut bounds {
            *r = r.subst(self.tcx, projection_ty.substs);
        }
        bounds
    }

    /// Given the def-id of an associated item, returns any region
    /// bounds attached to that associated item from the trait definition.
    ///
    /// For example:
    ///
    /// ```rust
    /// trait Foo<'a> {
    ///     type Bar: 'a;
    /// }
    /// ```
    ///
    /// If we were given the def-id of `Foo::Bar`, we would return
    /// `'a`. You could then apply the substitutions from the
    /// projection to convert this into your namespace. This also
    /// works if the user writes `where <Self as Foo<'a>>::Bar: 'a` on
    /// the trait. In fact, it works by searching for just such a
    /// where-clause.
    ///
    /// It will not, however, work for higher-ranked bounds like:
    ///
    /// ```rust
    /// trait Foo<'a, 'b>
    /// where for<'x> <Self as Foo<'x, 'b>>::Bar: 'x
    /// {
    ///     type Bar;
    /// }
    /// ```
    ///
    /// This is for simplicity, and because we are not really smart
    /// enough to cope with such bounds anywhere.
    fn region_bounds_declared_on_associated_item(
        &self,
        assoc_item_def_id: DefId,
    ) -> Vec<ty::Region<'tcx>> {
        let tcx = self.tcx;
        let assoc_item = tcx.associated_item(assoc_item_def_id);
        let trait_def_id = assoc_item.container.assert_trait();
        let trait_predicates = tcx.predicates_of(trait_def_id);
        let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id);
        let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
        self.collect_outlives_from_predicate_list(
            identity_proj,
            traits::elaborate_predicates(tcx, trait_predicates.predicates),
        )
    }

    /// Searches through a predicate list for a predicate `T: 'a`.
    ///
    /// Careful: does not elaborate predicates, and just uses `==`
    /// when comparing `ty` for equality, so `ty` must be something
    /// that does not involve inference variables and where you
    /// otherwise want a precise match.
    fn collect_outlives_from_predicate_list<I, P>(
        &self,
        ty: Ty<'tcx>,
        predicates: I,
    ) -> Vec<ty::Region<'tcx>>
    where
        I: IntoIterator<Item = P>,
        P: AsRef<ty::Predicate<'tcx>>,
    {
        predicates
            .into_iter()
            .filter_map(|p| p.as_ref().to_opt_type_outlives())
            .filter_map(|p| p.no_late_bound_regions())
            .filter(|p| p.0 == ty)
            .map(|p| p.1)
            .collect()
    }
}
<commit_msg>introduce a "comparison fn" instead of always use `==`<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use infer::outlives::env::RegionBoundPairs;
use infer::{GenericKind, VerifyBound};
use traits;
use ty::subst::{Subst, Substs};
use ty::{self, Ty, TyCtxt};

/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
/// obligation into a series of `'a: 'b` constraints and "verifys", as
/// described on the module comment. The final constraints are emitted
/// via a "delegate" of type `D` -- this is usually the `infcx`, which
/// accrues them into the `region_obligations` code, but for NLL we
/// use something else.
pub struct VerifyBoundCx<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
    region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
    implicit_region_bound: Option<ty::Region<'tcx>>,
    param_env: ty::ParamEnv<'tcx>,
}

impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
    pub fn new(
        tcx: TyCtxt<'cx, 'gcx, 'tcx>,
        region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
        implicit_region_bound: Option<ty::Region<'tcx>>,
        param_env: ty::ParamEnv<'tcx>,
    ) -> Self {
        Self {
            tcx,
            region_bound_pairs,
            implicit_region_bound,
            param_env,
        }
    }

    /// Returns a "verify bound" that encodes what we know about
    /// `generic` and the regions it outlives.
    pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
        match generic {
            GenericKind::Param(param_ty) => self.param_bound(param_ty),
            GenericKind::Projection(projection_ty) => self.projection_bound(projection_ty),
        }
    }

    fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
        match ty.sty {
            ty::Param(p) => self.param_bound(p),
            ty::Projection(data) => self.projection_bound(data),
            _ => self.recursive_type_bound(ty),
        }
    }

    fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
        debug!("param_bound(param_ty={:?})", param_ty);

        let mut param_bounds = self.declared_generic_bounds_from_env(GenericKind::Param(param_ty));

        // Add in the default bound of fn body that applies to all in
        // scope type parameters:
        param_bounds.extend(self.implicit_region_bound);

        VerifyBound::AnyRegion(param_bounds)
    }

    /// Given a projection like `T::Item`, searches the environment
    /// for where-clauses like `T::Item: 'a`. Returns the set of
    /// regions `'a` that it finds.  This is a "conservative" check --
    /// it may not find all applicable bounds, but all the bounds it
    /// returns can be relied upon.
    pub fn projection_declared_bounds_from_env(
        &self,
        projection_ty: ty::ProjectionTy<'tcx>,
    ) -> Vec<ty::Region<'tcx>> {
        self.declared_generic_bounds_from_env(GenericKind::Projection(projection_ty))
    }

    /// Searches the where clauses in scope for regions that
    /// `projection_ty` is known to outlive. Currently requires an
    /// exact match.
    pub fn projection_declared_bounds_from_trait(
        &self,
        projection_ty: ty::ProjectionTy<'tcx>,
    ) -> Vec<ty::Region<'tcx>> {
        self.declared_projection_bounds_from_trait(projection_ty)
    }

    pub fn projection_bound(
        &self,
        projection_ty: ty::ProjectionTy<'tcx>,
    ) -> VerifyBound<'tcx> {
        debug!(
            "projection_bound(projection_ty={:?})",
            projection_ty
        );

        let mut declared_bounds =
            self.projection_declared_bounds_from_env(projection_ty);

        declared_bounds.extend(
            self.projection_declared_bounds_from_trait(projection_ty)
        );

        debug!("projection_bound: declared_bounds = {:?}", declared_bounds);

        // see the extensive comment in projection_must_outlive
        let ty = self.tcx
            .mk_projection(projection_ty.item_def_id, projection_ty.substs);
        let recursive_bound = self.recursive_type_bound(ty);

        VerifyBound::AnyRegion(declared_bounds).or(recursive_bound)
    }

    fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
        let mut bounds = ty.walk_shallow()
            .map(|subty| self.type_bound(subty))
            .collect::<Vec<_>>();

        let mut regions = ty.regions();
        regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
        bounds.push(VerifyBound::AllRegions(regions));

        // remove bounds that must hold, since they are not interesting
        bounds.retain(|b| !b.must_hold());

        if bounds.len() == 1 {
            bounds.pop().unwrap()
        } else {
            VerifyBound::AllBounds(bounds)
        }
    }

    fn declared_generic_bounds_from_env(
        &self,
        generic: GenericKind<'tcx>,
    ) -> Vec<ty::Region<'tcx>> {
        let tcx = self.tcx;

        // To start, collect bounds from user environment. Note that
        // parameter environments are already elaborated, so we don't
        // have to worry about that. Comparing using `==` is a bit
        // dubious for projections, but it will work for simple cases
        // like `T` and `T::Item`. It may not work as well for things
        // like `<T as Foo<'a>>::Item`.
        let generic_ty = generic.to_ty(tcx);
        let c_b = self.param_env.caller_bounds;
        let mut param_bounds = self.collect_outlives_from_predicate_list(
            |ty| ty == generic_ty,
            c_b,
        );

        // Next, collect regions we scraped from the well-formedness
        // constraints in the fn signature. To do that, we walk the list
        // of known relations from the fn ctxt.
        //
        // This is crucial because otherwise code like this fails:
        //
        //     fn foo<'a, A>(x: &'a A) { x.bar() }
        //
        // The problem is that the type of `x` is `&'a A`. To be
        // well-formed, then, A must be lower-generic by `'a`, but we
        // don't know that this holds from first principles.
        for &(r, p) in self.region_bound_pairs {
            debug!("generic={:?} p={:?}", generic, p);
            if generic == p {
                param_bounds.push(r);
            }
        }

        param_bounds
    }

    /// Given a projection like `<T as Foo<'x>>::Bar`, returns any bounds
    /// declared in the trait definition. For example, if the trait were
    ///
    /// ```rust
    /// trait Foo<'a> {
    ///     type Bar: 'a;
    /// }
    /// ```
    ///
    /// then this function would return `'x`. This is subject to the
    /// limitations around higher-ranked bounds described in
    /// `region_bounds_declared_on_associated_item`.
    fn declared_projection_bounds_from_trait(
        &self,
        projection_ty: ty::ProjectionTy<'tcx>,
    ) -> Vec<ty::Region<'tcx>> {
        debug!("projection_bounds(projection_ty={:?})", projection_ty);
        let mut bounds = self.region_bounds_declared_on_associated_item(projection_ty.item_def_id);
        for r in &mut bounds {
            *r = r.subst(self.tcx, projection_ty.substs);
        }
        bounds
    }

    /// Given the def-id of an associated item, returns any region
    /// bounds attached to that associated item from the trait definition.
    ///
    /// For example:
    ///
    /// ```rust
    /// trait Foo<'a> {
    ///     type Bar: 'a;
    /// }
    /// ```
    ///
    /// If we were given the def-id of `Foo::Bar`, we would return
    /// `'a`. You could then apply the substitutions from the
    /// projection to convert this into your namespace. This also
    /// works if the user writes `where <Self as Foo<'a>>::Bar: 'a` on
    /// the trait. In fact, it works by searching for just such a
    /// where-clause.
    ///
    /// It will not, however, work for higher-ranked bounds like:
    ///
    /// ```rust
    /// trait Foo<'a, 'b>
    /// where for<'x> <Self as Foo<'x, 'b>>::Bar: 'x
    /// {
    ///     type Bar;
    /// }
    /// ```
    ///
    /// This is for simplicity, and because we are not really smart
    /// enough to cope with such bounds anywhere.
    fn region_bounds_declared_on_associated_item(
        &self,
        assoc_item_def_id: DefId,
    ) -> Vec<ty::Region<'tcx>> {
        let tcx = self.tcx;
        let assoc_item = tcx.associated_item(assoc_item_def_id);
        let trait_def_id = assoc_item.container.assert_trait();
        let trait_predicates = tcx.predicates_of(trait_def_id);
        let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id);
        let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
        self.collect_outlives_from_predicate_list(
            |ty| ty == identity_proj,
            traits::elaborate_predicates(tcx, trait_predicates.predicates),
        )
    }

    /// Searches through a predicate list for a predicate `T: 'a`.
    ///
    /// Careful: does not elaborate predicates, and just uses `==`
    /// when comparing `ty` for equality, so `ty` must be something
    /// that does not involve inference variables and where you
    /// otherwise want a precise match.
    fn collect_outlives_from_predicate_list(
        &self,
        compare_ty: impl Fn(Ty<'tcx>) -> bool,
        predicates: impl IntoIterator<Item = impl AsRef<ty::Predicate<'tcx>>>,
    ) -> Vec<ty::Region<'tcx>> {
        predicates
            .into_iter()
            .filter_map(|p| p.as_ref().to_opt_type_outlives())
            .filter_map(|p| p.no_late_bound_regions())
            .filter(|p| compare_ty(p.0))
            .map(|p| p.1)
            .collect()
    }
}
<|endoftext|>


<commit_before>//! An example demonstrating sRGB color spaces.
//!
//! sRGB is one of those things that's a bit subtle, a bit obscure,
//! and easy to get wrong, but worth knowing because it crops up
//! from time to time and makes things mysteriously "look wrong" in
//! some cases.  It also is sort of overloaded to do two things at
//! once.  The first is what you will find [Wikipedia talking about](https://en.wikipedia.org/wiki/Srgb),
//! which is "how do you prove that 'green' on my monitor is the same
//! as 'green' on your monitor?".  That part we can safely ignore,
//! since it's a job for your monitor manufacturer.
//!
//! The other part is [gamma
//! correction](https://en.wikipedia.org/wiki/Gamma_correction) which
//! deals with the fact that the response of the human visual system
//! is non-linear, or in non-science talk, if you make a pixel twice
//! as bright, it doesn't *look* twice as bright.  To make something
//! *look* twice as bright, you have to make it about 2^2.2 times
//! brighter.  The exact math for how to fiddle the numbers to make
//! things Look Nice is defined as part of the sRGB standard, so often
//! a color scheme that complies with this gamma correction process is
//! just called "sRGB".
//!
//! In a perfect world, we don't ever have to worry about this.
//! Images are generally all stored in the sRGB color space (or
//! something similar to it), monitors all display in the sRGB color
//! space, and our graphics drivers know how to do whatever is
//! necessary to make the two line up.  The problem comes because we
//! are programmers, and have to be able to poke things instead of
//! just using pre-loaded assets.  So the question is: if you do
//! `Color::new(0.5, 0.0, 0.0, 1.0)` and `Color::new(1.0, 0.0, 0.0, 1.0)`,
//! will the second color LOOK twice as bright as the first one?
//!
//! So we have to know what color space we are talking about when we
//! say `Color`!  Are we talking about linear, "real" color where your
//! pixel puts out twice as many photons for the second color as the
//! first?  Or are we talking about sRGB color, where the pixel
//! actually LOOKS twice as bright?  And if we want to, say, write a
//! shader that does math to these colors, AND to colors that come
//! from images that use the sRGB color space, how do we make sure
//! everything matches?  To make it even worse, the sRGB conversion
//! done by graphics drivers is toggle-able, and can be set on a
//! per-render-target or per-texture basis, so it's possible for
//! things to get REAL mixed up in subtle ways.
//!
//! The Right Answer, as far as I know, is this: All colors that a
//! human specifies or touches are sRGB-encoded, so a number that is
//! twice as big then .  We do our color math in shaders, and (if we
//! set our render target to be an sRGB texture, which ggez always
//! does) the graphics driver will turn the linear colors we specify
//! into sRGB colors.  So if we do `vec4 x = vec4(0.25, 0.0, 0.0, 1.0);`,
//! assigning one pixel `x` and another `x * 2` will make the
//! second one *look* twice as bright as the first.
//!
//! BUT, this process also has to be done on INPUT as well; if we pass
//! the shader a value taken from an image file, that image file is in
//! sRGB color.  The graphics driver must THEN convert the sRGB color into
//! a linear color when passing it to the shader, so that if we get the
//! color and call it `x`, assigning one output pixel `x` and another
//! `x * 2` again makes the second one LOOK twice as bright as the first.
//! Then it converts the value back on the way out.
//!
//! ggez should handle all of this for you.  `graphics::Color` is
//! explicitly a sRGB-corrected color, all textures including the
//! final render target are sRGB-enabled, and when you provide
//! a linear color to something like `graphics::Mesh` it turns it
//! into sRGB for you to match everything else.  The purpose of this
//! example is to show that this actually *works* correctly!

use ggez;
use ggez::event;
use ggez::graphics::{self, DrawParam};
use ggez::nalgebra as na;
use ggez::{Context, GameResult};

/// This is a nice aqua test color that will look a lot brighter
/// than it should if we mess something up.
/// See https://github.com/ggez/ggez/issues/209 for examples.
const AQUA: graphics::Color = graphics::Color::new(0.0078, 0.7647, 0.6039, 1.0);

struct MainState {
    demo_mesh: graphics::Mesh,
    square_mesh: graphics::Mesh,
    demo_image: graphics::Image,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let demo_mesh = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::fill(),
            na::Point2::new(0.0, 0.0),
            100.0,
            2.0,
            AQUA,
        )?;
        let square_mesh = graphics::Mesh::new_rectangle(
            ctx,
            graphics::DrawMode::fill(),
            graphics::Rect::new(0.0, 0.0, 400.0, 400.0),
            graphics::WHITE
        )?;
        let demo_image = graphics::Image::solid(ctx, 100, AQUA)?;
        let s = MainState { demo_mesh, square_mesh, demo_image };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, AQUA);

        // Draw a white square so we can see things
        graphics::draw(ctx, &self.square_mesh, DrawParam::default()
                       .dest(na::Point2::new(200.0, 100.0)))?;

        // Draw things partially over the white square so we can see
        // where they are; they SHOULD be the same color as the
        // background.
        graphics::draw(ctx, &self.demo_mesh, DrawParam::default()
                       .dest(na::Point2::new(150.0, 200.0)))?;

        graphics::draw(ctx, &self.demo_image, DrawParam::default()
                       .dest(na::Point2::new(450.0, 200.0)))?;

        graphics::present(ctx)?;
        Ok(())
    }
}

pub fn main() -> GameResult {
    use std::env;
    use std::path;
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("super_simple", "ggez").add_resource_path(resource_dir);
    let (ctx, event_loop) = &mut cb.build()?;
    let state = &mut MainState::new(ctx)?;
    event::run(ctx, event_loop, state)
}

<commit_msg>Fiddle coords on colorspace example.<commit_after>//! An example demonstrating sRGB color spaces.
//!
//! sRGB is one of those things that's a bit subtle, a bit obscure,
//! and easy to get wrong, but worth knowing because it crops up
//! from time to time and makes things mysteriously "look wrong" in
//! some cases.  It also is sort of overloaded to do two things at
//! once.  The first is what you will find [Wikipedia talking about](https://en.wikipedia.org/wiki/Srgb),
//! which is "how do you prove that 'green' on my monitor is the same
//! as 'green' on your monitor?".  That part we can safely ignore,
//! since it's a job for your monitor manufacturer.
//!
//! The other part is [gamma
//! correction](https://en.wikipedia.org/wiki/Gamma_correction) which
//! deals with the fact that the response of the human visual system
//! is non-linear, or in non-science talk, if you make a pixel twice
//! as bright, it doesn't *look* twice as bright.  To make something
//! *look* twice as bright, you have to make it about 2^2.2 times
//! brighter.  The exact math for how to fiddle the numbers to make
//! things Look Nice is defined as part of the sRGB standard, so often
//! a color scheme that complies with this gamma correction process is
//! just called "sRGB".
//!
//! In a perfect world, we don't ever have to worry about this.
//! Images are generally all stored in the sRGB color space (or
//! something similar to it), monitors all display in the sRGB color
//! space, and our graphics drivers know how to do whatever is
//! necessary to make the two line up.  The problem comes because we
//! are programmers, and have to be able to poke things instead of
//! just using pre-loaded assets.  So the question is: if you do
//! `Color::new(0.5, 0.0, 0.0, 1.0)` and `Color::new(1.0, 0.0, 0.0, 1.0)`,
//! will the second color LOOK twice as bright as the first one?
//!
//! So we have to know what color space we are talking about when we
//! say `Color`!  Are we talking about linear, "real" color where your
//! pixel puts out twice as many photons for the second color as the
//! first?  Or are we talking about sRGB color, where the pixel
//! actually LOOKS twice as bright?  And if we want to, say, write a
//! shader that does math to these colors, AND to colors that come
//! from images that use the sRGB color space, how do we make sure
//! everything matches?  To make it even worse, the sRGB conversion
//! done by graphics drivers is toggle-able, and can be set on a
//! per-render-target or per-texture basis, so it's possible for
//! things to get REAL mixed up in subtle ways.
//!
//! The Right Answer, as far as I know, is this: All colors that a
//! human specifies or touches are sRGB-encoded, so a number that is
//! twice as big then .  We do our color math in shaders, and (if we
//! set our render target to be an sRGB texture, which ggez always
//! does) the graphics driver will turn the linear colors we specify
//! into sRGB colors.  So if we do `vec4 x = vec4(0.25, 0.0, 0.0, 1.0);`,
//! assigning one pixel `x` and another `x * 2` will make the
//! second one *look* twice as bright as the first.
//!
//! BUT, this process also has to be done on INPUT as well; if we pass
//! the shader a value taken from an image file, that image file is in
//! sRGB color.  The graphics driver must THEN convert the sRGB color into
//! a linear color when passing it to the shader, so that if we get the
//! color and call it `x`, assigning one output pixel `x` and another
//! `x * 2` again makes the second one LOOK twice as bright as the first.
//! Then it converts the value back on the way out.
//!
//! ggez should handle all of this for you.  `graphics::Color` is
//! explicitly a sRGB-corrected color, all textures including the
//! final render target are sRGB-enabled, and when you provide
//! a linear color to something like `graphics::Mesh` it turns it
//! into sRGB for you to match everything else.  The purpose of this
//! example is to show that this actually *works* correctly!

use ggez;
use ggez::event;
use ggez::graphics::{self, DrawParam};
use ggez::nalgebra as na;
use ggez::{Context, GameResult};

/// This is a nice aqua test color that will look a lot brighter
/// than it should if we mess something up.
/// See https://github.com/ggez/ggez/issues/209 for examples.
const AQUA: graphics::Color = graphics::Color::new(0.0078, 0.7647, 0.6039, 1.0);

struct MainState {
    demo_mesh: graphics::Mesh,
    square_mesh: graphics::Mesh,
    demo_image: graphics::Image,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let demo_mesh = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::fill(),
            na::Point2::new(0.0, 0.0),
            100.0,
            2.0,
            AQUA,
        )?;
        let square_mesh = graphics::Mesh::new_rectangle(
            ctx,
            graphics::DrawMode::fill(),
            graphics::Rect::new(0.0, 0.0, 400.0, 400.0),
            graphics::WHITE
        )?;
        let demo_image = graphics::Image::solid(ctx, 200, AQUA)?;
        let s = MainState { demo_mesh, square_mesh, demo_image };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, AQUA);

        // Draw a white square so we can see things
        graphics::draw(ctx, &self.square_mesh, DrawParam::default()
                       .dest(na::Point2::new(200.0, 100.0)))?;

        // Draw things partially over the white square so we can see
        // where they are; they SHOULD be the same color as the
        // background.
        graphics::draw(ctx, &self.demo_mesh, DrawParam::default()
                       .dest(na::Point2::new(150.0, 200.0)))?;

        graphics::draw(ctx, &self.demo_image, DrawParam::default()
                       .dest(na::Point2::new(450.0, 200.0)))?;

        graphics::present(ctx)?;
        Ok(())
    }
}

pub fn main() -> GameResult {
    use std::env;
    use std::path;
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("super_simple", "ggez").add_resource_path(resource_dir);
    let (ctx, event_loop) = &mut cb.build()?;
    let state = &mut MainState::new(ctx)?;
    event::run(ctx, event_loop, state)
}

<|endoftext|>