<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

extern crate wayland_client;
use wayland_client::client::{FromPrimitive, Display,
                             Registry, RegistryEventHandler,
                             Seat, SeatEventHandler, SeatCapability,
                             Shm, ShmEventHandler, ShmFormat,
                             Output, OutputEventHandler, OutputSubpixel,
                             OutputTransform, OutputMode};

use std::collections::HashMap;

#[derive(Default)]
struct SeatData {
    name: String,
    capabilities: Vec<String>,
}

#[derive(Default)]
struct ShmData {
    formats: Vec<String>,
}

#[derive(Default)]
struct OutputData {
    x: i32,
    y: i32,
    physical_width: i32,
    physical_height: i32,
    subpixel: String,
    make: String,
    model: String,
    transform: String,
    modes: Vec<OutputModeData>,
}

struct OutputModeData {
    width: i32,
    height: i32,
    refresh: i32,
    flags: String,
}

struct Info {
    registry: Registry,
    seat: Option<Seat>,
    shm: Option<Shm>,
    output: Option<Output>,
    pub roundtrip: bool,
    data: HashMap<String, String>,
    seat_data: SeatData,
    shm_data: ShmData,
    output_data: OutputData,
}

impl Info {
    fn new(registry: Registry) -> Info {
        return Info {
            registry: registry,
            seat: None,
            shm: None,
            output: None,
            roundtrip: true,
            data: HashMap::new(),
            seat_data: Default::default(),
            shm_data: Default::default(),
            output_data: Default::default(),
        };
    }
}

impl RegistryEventHandler for Info {
    fn get_registry(&mut self) -> &mut Registry {
        return &mut self.registry;
    }

    fn on_global(&mut self, name: u32, interface: String, version: u32) {
        self.data.insert(interface.clone(),
                         format!("interface: '{}', version: {}, name: {}",
                                 interface, version, name));

        if interface == "wl_seat" {
            self.roundtrip = true;
            self.seat = self.registry.bind(name, version).ok();
            SeatEventHandler::connect_dispatcher(self);
        } else if interface == "wl_shm" {
            self.roundtrip = true;
            self.shm = self.registry.bind(name, version).ok();
            ShmEventHandler::connect_dispatcher(self);
        } else if interface == "wl_output" {
            self.roundtrip = true;
            self.output = self.registry.bind(name, version).ok();
            OutputEventHandler::connect_dispatcher(self);
        }
    }
}

impl SeatEventHandler for Info {
    fn get_seat(&mut self) -> &mut Seat {
        return self.seat.as_mut().unwrap();
    }

    fn on_capabilities(&mut self, capabilities: u32) {
        if capabilities & (SeatCapability::Pointer as u32) != 0 {
            self.seat_data.capabilities.push("pointer".to_string());
        }
        if capabilities & (SeatCapability::Keyboard as u32) != 0 {
            self.seat_data.capabilities.push("keyboard".to_string());
        }
        if capabilities & (SeatCapability::Touch as u32) != 0 {
            self.seat_data.capabilities.push("touch".to_string());
        }
    }

    fn on_name(&mut self, name: String) {
        self.seat_data.name = name;
    }
}

impl ShmEventHandler for Info {
    fn get_shm(&mut self) -> &mut Shm {
        return self.shm.as_mut().unwrap();
    }

    fn on_format(&mut self, format: u32) {
        self.shm_data.formats.push(format!("{:?}", ShmFormat::from_u32(format).unwrap()));
    }
}

impl OutputEventHandler for Info {
    fn get_output(&mut self) -> &mut Output {
        return self.output.as_mut().unwrap();
    }

    fn on_geometry(&mut self, x: i32, y: i32, physical_width: i32,
                   physical_height: i32, subpixel: i32, make: String, model:
                   String, transform: i32) {
        self.output_data.x = x;
        self.output_data.y = y;
        self.output_data.physical_width = physical_width;
        self.output_data.physical_height = physical_height;
        self.output_data.subpixel = format!("{:?}", OutputSubpixel::from_u32(subpixel as u32).unwrap());
        self.output_data.make = make;
        self.output_data.model = model;
        self.output_data.transform = format!("{:?}", OutputTransform::from_u32(transform as u32).unwrap());
    }

    fn on_mode(&mut self, flags: u32, width: i32, height: i32, refresh: i32) {
        let mut flags_ = Vec::new();
        if flags & (OutputMode::Current as u32) != 0 {
            flags_.push("current".to_string());
        }
        if flags & (OutputMode::Preferred as u32) != 0 {
            flags_.push("preferred".to_string());
        }
        self.output_data.modes.push(OutputModeData {
            width: width,
            height: height,
            refresh: refresh,
            flags: flags_.connect(" "),
        })
    }
}

fn main() {
    let mut display = Display::connect(None).unwrap();
    let mut info = Info::new(display.get_registry().unwrap());
    RegistryEventHandler::connect_dispatcher(&mut info);

    while info.roundtrip {
        info.roundtrip = false;
        display.roundtrip();
    }
}
<commit_msg>weston-info: print the data<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

extern crate wayland_client;
use wayland_client::client::{FromPrimitive, Display,
                             Registry, RegistryEventHandler,
                             Seat, SeatEventHandler, SeatCapability,
                             Shm, ShmEventHandler, ShmFormat,
                             Output, OutputEventHandler, OutputSubpixel,
                             OutputTransform, OutputMode};

use std::collections::HashMap;

#[derive(Default)]
struct SeatData {
    name: String,
    capabilities: Vec<String>,
}

#[derive(Default)]
struct ShmData {
    formats: Vec<String>,
}

#[derive(Default)]
struct OutputData {
    x: i32,
    y: i32,
    physical_width: i32,
    physical_height: i32,
    subpixel: String,
    make: String,
    model: String,
    transform: String,
    modes: Vec<OutputModeData>,
}

struct OutputModeData {
    width: i32,
    height: i32,
    refresh: i32,
    flags: String,
}

struct Info {
    registry: Registry,
    seat: Option<Seat>,
    shm: Option<Shm>,
    output: Option<Output>,
    pub roundtrip: bool,
    data: HashMap<String, String>,
    seat_data: SeatData,
    shm_data: ShmData,
    output_data: OutputData,
}

impl Info {
    fn new(registry: Registry) -> Info {
        return Info {
            registry: registry,
            seat: None,
            shm: None,
            output: None,
            roundtrip: true,
            data: HashMap::new(),
            seat_data: Default::default(),
            shm_data: Default::default(),
            output_data: Default::default(),
        };
    }

    fn print_it(&self) {
        for (key, val) in self.data.iter() {
            println!("{}", val);
            match key.as_ref() {
                "wl_shm" => {
                    println!("\tformats: {}",
                             self.shm_data.formats.connect(" "));
                },
                "wl_seat" => {
                    println!("\tname: {}", self.seat_data.name);
                    println!("\tcapabilities: {}",
                             self.seat_data.capabilities.connect(" "));
                },
                "wl_output" => {
                    println!("\tx: {}, y: {},", self.output_data.x,
                             self.output_data.y);
                    println!("\tphysical_width: {} mm, physical_height: {} mm,",
                             self.output_data.physical_width,
                             self.output_data.physical_height);
                    println!("\tmake: '{}', model: '{}',",
                             self.output_data.make, self.output_data.model);
                    println!("\tsubpixel_orientation: '{}', transformation: '{}',",
                             self.output_data.subpixel,
                             self.output_data.transform);
                    for mode in self.output_data.modes.iter() {
                        println!("\tmode:");
                        println!("\t\twidth: {} px, height: {} px, refresh: {} Hz,",
                                 mode.width, mode.height, mode.refresh / 1000);
                        println!("\t\tflags: {}", mode.flags);
                    }
                }
                _ => (),
            }
        }
    }
}

impl RegistryEventHandler for Info {
    fn get_registry(&mut self) -> &mut Registry {
        return &mut self.registry;
    }

    fn on_global(&mut self, name: u32, interface: String, version: u32) {
        self.data.insert(interface.clone(),
                         format!("interface: '{}', version: {}, name: {}",
                                 interface, version, name));

        if interface == "wl_seat" {
            self.roundtrip = true;
            self.seat = self.registry.bind(name, version).ok();
            SeatEventHandler::connect_dispatcher(self);
        } else if interface == "wl_shm" {
            self.roundtrip = true;
            self.shm = self.registry.bind(name, version).ok();
            ShmEventHandler::connect_dispatcher(self);
        } else if interface == "wl_output" {
            self.roundtrip = true;
            self.output = self.registry.bind(name, version).ok();
            OutputEventHandler::connect_dispatcher(self);
        }
    }
}

impl SeatEventHandler for Info {
    fn get_seat(&mut self) -> &mut Seat {
        return self.seat.as_mut().unwrap();
    }

    fn on_capabilities(&mut self, capabilities: u32) {
        if capabilities & (SeatCapability::Pointer as u32) != 0 {
            self.seat_data.capabilities.push("pointer".to_string());
        }
        if capabilities & (SeatCapability::Keyboard as u32) != 0 {
            self.seat_data.capabilities.push("keyboard".to_string());
        }
        if capabilities & (SeatCapability::Touch as u32) != 0 {
            self.seat_data.capabilities.push("touch".to_string());
        }
    }

    fn on_name(&mut self, name: String) {
        self.seat_data.name = name;
    }
}

impl ShmEventHandler for Info {
    fn get_shm(&mut self) -> &mut Shm {
        return self.shm.as_mut().unwrap();
    }

    fn on_format(&mut self, format: u32) {
        self.shm_data.formats.push(format!("{:?}", ShmFormat::from_u32(format).unwrap()));
    }
}

impl OutputEventHandler for Info {
    fn get_output(&mut self) -> &mut Output {
        return self.output.as_mut().unwrap();
    }

    fn on_geometry(&mut self, x: i32, y: i32, physical_width: i32,
                   physical_height: i32, subpixel: i32, make: String, model:
                   String, transform: i32) {
        self.output_data.x = x;
        self.output_data.y = y;
        self.output_data.physical_width = physical_width;
        self.output_data.physical_height = physical_height;
        self.output_data.subpixel = format!("{:?}", OutputSubpixel::from_u32(subpixel as u32).unwrap());
        self.output_data.make = make;
        self.output_data.model = model;
        self.output_data.transform = format!("{:?}", OutputTransform::from_u32(transform as u32).unwrap());
    }

    fn on_mode(&mut self, flags: u32, width: i32, height: i32, refresh: i32) {
        let mut flags_ = Vec::new();
        if flags & (OutputMode::Current as u32) != 0 {
            flags_.push("current".to_string());
        }
        if flags & (OutputMode::Preferred as u32) != 0 {
            flags_.push("preferred".to_string());
        }
        self.output_data.modes.push(OutputModeData {
            width: width,
            height: height,
            refresh: refresh,
            flags: flags_.connect(" "),
        })
    }
}

fn main() {
    let mut display = Display::connect(None).unwrap();
    let mut info = Info::new(display.get_registry().unwrap());
    RegistryEventHandler::connect_dispatcher(&mut info);

    while info.roundtrip {
        info.roundtrip = false;
        display.roundtrip();
    }
    info.print_it();
}
<|endoftext|>


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

use std::cmp::max;
use std::collections::HashMap;

use glib::{Cast, Object};
use gtk;
use gtk::{
    Align,
    CellLayoutExt,
    CellRendererText,
    CellRendererTextExt,
    IsA,
    ListStore,
    ScrolledWindowExt,
    TreeIter,
    TreeModel,
    TreeModelExt,
    TreeSelection,
    TreeViewColumn,
    WidgetExt,
};
use gtk::PolicyType::{Automatic, Never};
use pango::EllipsizeMode;
use relm::{Relm, Widget};
use relm_attributes::widget;

use app::COMMAND_MODE;
use completion::Column::{self, Expand};
use super::{Completer, Completion, DEFAULT_COMPLETER_IDENT, NO_COMPLETER_IDENT};

const COMPLETION_VIEW_MAX_HEIGHT: i32 = 300;

#[allow(missing_docs)]
pub struct Model {
    completion: Completion,
    original_input: String,
    visible: bool,
}

/// A widget to show completions for the command entry.
#[widget]
impl Widget for CompletionView {
    fn init_view(&mut self) {
        self.add_columns(2);
    }

    fn model(_relm: &Relm<Self>, _: ()) -> Model {
        Model {
            completion: Completion::new(),
            original_input: String::new(),
            visible: false,
        }
    }

    /// Set the visibility of the view.
    pub fn set_visible(&mut self, visible: bool) {
        self.model.visible = visible;
    }

    /// Show the completion view.
    pub fn show_completion(&mut self) {
        self.unselect();
        self.scroll_to_first();
        self.model.visible = true;
    }

    fn update(&mut self, _event: ()) {
    }

    view! {
        #[name="scrolled_window"]
        gtk::ScrolledWindow {
            max_content_height: COMPLETION_VIEW_MAX_HEIGHT,
            propagate_natural_height: true,
            valign: Align::End,
            visible: self.model.visible,
            #[name="tree_view"]
            gtk::TreeView {
                can_focus: false,
                enable_search: false,
                headers_visible: false,
            }
        }
    }
}

impl CompletionView {
    /// Add a column to the tree view.
    fn add_column(&self, index: i32, foreground_index: i32, column: Column) {
        let view_column = TreeViewColumn::new();
        let cell = CellRendererText::new();
        if column == Expand {
            cell.set_property_ellipsize(EllipsizeMode::End);
            view_column.set_expand(true);
        }
        view_column.pack_start(&cell, true);
        view_column.add_attribute(&cell, "text", index);
        view_column.add_attribute(&cell, "foreground", foreground_index);
        self.tree_view.append_column(&view_column);
    }

    /// Add the specified number of columns.
    fn add_columns(&self, column_count: i32) {
        self.remove_columns();
        for i in 0 .. column_count {
            self.add_column(i, column_count + i, Expand);
        }
    }

    /// Add the specified number of columns.
    fn add_columns_from_completer(&self, completer: &Completer) {
        self.remove_columns();
        let columns = completer.columns();
        let column_count = columns.len() as i32;
        for (i, column) in columns.iter().enumerate() {
            let i = i as i32;
            self.add_column(i, column_count + i, *column);
        }
    }

    /// Adjust the columns from the completer.
    pub fn adjust_columns(&self, completer: &Completer) {
        self.add_columns_from_completer(completer);
    }

    /// Adjust the policy of the scrolled window to avoid having extra space around the tree view.
    pub fn adjust_policy<M: IsA<Object> + IsA<TreeModel>>(&self, model: &M) {
        self.tree_view.set_model(Some(model));
        let policy =
            if model.iter_n_children(None) < 2 {
                Never
            }
            else {
                Automatic
            };
        self.scrolled_window.set_policy(Never, policy);
    }

    /// Complete the result for the selection using the current completer.
    pub fn complete_result(&self, selection: &TreeSelection) -> Option<String> {
        self.model.completion.complete_result(selection)
    }

    /// Delete the current completion item.
    pub fn delete_current_completion_item(&self) {
        if let Some((model, iter)) = self.tree_view.get_selection().get_selected() {
            if let Ok(model) = model.downcast::<ListStore>() {
                self.select_next();
                model.remove(&iter);
            }
        }
    }

    /// Adjust the policy of the scrolled window to avoid having extra space around the tree view.
    pub fn disable_scrollbars(&self) {
        self.scrolled_window.set_policy(Never, Never);
    }

    /// Filter the completion view.
    fn filter(&mut self, command_entry_text: &str) {
        // Disable the scrollbars so that commands without completion does not
        // show the completion view.
        self.disable_scrollbars();
        let model = self.model.completion.filter(command_entry_text);
        if let Some(model) = model {
            self.adjust_policy(&model);
        }
    }

    /// Get the original input.
    pub fn original_input(&self) -> &str {
        &self.model.original_input
    }

    /// Remove all the columns.
    fn remove_columns(&self) {
        for column in &self.tree_view.get_columns() {
            self.tree_view.remove_column(column);
        }
    }

    /// Scroll to the selected row.
    fn scroll(&self, model: &TreeModel, iter: &TreeIter) {
        if let Some(path) = model.get_path(iter) {
            self.tree_view.scroll_to_cell(Some(&path), None, false, 0.0, 0.0);
        }
    }

    /// Scroll to the first row.
    pub fn scroll_to_first(&self) {
        if let Some(model) = self.tree_view.get_model() {
            if let Some(iter) = model.get_iter_first() {
                if let Some(path) = model.get_path(&iter) {
                    self.tree_view.scroll_to_cell(Some(&path), None, false, 0.0, 0.0);
                }
            }
        }
    }

    /// Select the completer based on the currently typed command.
    pub fn select_completer(&mut self, command_entry_text: &str) {
        let text = command_entry_text.trim_left();
        if let Some(space_index) = text.find(' ') {
            let command = &text[..space_index];
            self.set_completer(command, command_entry_text);
        }
        else {
            self.set_completer(DEFAULT_COMPLETER_IDENT, command_entry_text);
        }
    }

    /// Select the next item.
    /// This loops with the value that started the completion.
    pub fn select_next(&self) -> (Option<TreeSelection>, bool) {
        let mut unselect = false;
        let selection =
            if let Some(model) = self.tree_view.get_model() {
                let selection = self.tree_view.get_selection();
                if let Some((model, selected_iter)) = selection.get_selected() {
                    if model.iter_next(&selected_iter) {
                        selection.select_iter(&selected_iter);
                        self.scroll(&model, &selected_iter);
                    }
                    else {
                        self.unselect();
                        unselect = true;
                    }
                }
                else if let Some(iter) = model.get_iter_first() {
                    self.scroll(&model, &iter);
                    selection.select_iter(&iter);
                }
                Some(selection)
            }
            else {
                None
            };
        (selection, unselect)
    }

    /// Select the previous item.
    /// This loops with the value that started the completion.
    pub fn select_previous(&self) -> (Option<TreeSelection>, bool) {
        let mut unselect = false;
        let selection =
            if let Some(model) = self.tree_view.get_model() {
                let selection = self.tree_view.get_selection();
                if let Some((model, selected_iter)) = selection.get_selected() {
                    if model.iter_previous(&selected_iter) {
                        selection.select_iter(&selected_iter);
                        self.scroll(&model, &selected_iter);
                    }
                    else {
                        self.unselect();
                        unselect = true;
                    }
                }
                else if let Some(iter) = model.iter_nth_child(None, max(0, model.iter_n_children(None) - 1)) {
                    self.scroll(&model, &iter);
                    selection.select_iter(&iter);
                }
                Some(selection)
            }
            else {
                None
            };
        (selection, unselect)
    }

    /// Set the current command completer.
    pub fn set_completer(&mut self, completer: &str, command_entry_text: &str) {
        if self.model.completion.adjust_model(completer) {
            let model: Option<&ListStore> = None;
            self.tree_view.set_model(model);
        }
        {
            let completer = self.model.completion.current_completer().expect("completer should be set");
            self.adjust_columns(&**completer);
        }
        self.filter(command_entry_text);
    }

    /// Set all the completers.
    pub fn set_completers(&mut self, completers: HashMap<String, Box<Completer>>) {
        self.model.completion.set_completers(completers);
    }

    /// Set the original input.
    pub fn set_original_input(&mut self, input: &str) {
        self.model.original_input = input.to_string();
    }

    /// Unselect the item.
    pub fn unselect(&self) {
        let selection = self.tree_view.get_selection();
        selection.unselect_all();
    }

    /// Update the completions.
    pub fn update_completions(&mut self, current_mode: &str, command_entry_text: &str) {
        if current_mode == COMMAND_MODE {
            // In command mode, the completer can change when the user type.
            // For instance, after typing "set ", the completer switch to the settings
            // completer.
            // TODO: add command_entry_text in the model?
            self.select_completer(command_entry_text);
        }
        else {
            // Do not select another completer when in input mode.
            self.filter(command_entry_text);
        }
        if self.model.completion.current_completer_ident() != NO_COMPLETER_IDENT {
            self.filter(command_entry_text);
            // return Some(SetOriginalInput(text); // TODO
            self.set_original_input(command_entry_text);
        }
        self.unselect();
    }
}
<commit_msg>Adjust the scrollbar policy when deleting completion items<commit_after>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

use std::cmp::max;
use std::collections::HashMap;

use glib::{Cast, Object};
use gtk;
use gtk::{
    Align,
    CellLayoutExt,
    CellRendererText,
    CellRendererTextExt,
    IsA,
    ListStore,
    ScrolledWindowExt,
    TreeIter,
    TreeModel,
    TreeModelExt,
    TreeSelection,
    TreeViewColumn,
    WidgetExt,
};
use gtk::PolicyType::{Automatic, Never};
use pango::EllipsizeMode;
use relm::{Relm, Widget};
use relm_attributes::widget;

use app::COMMAND_MODE;
use completion::Column::{self, Expand};
use super::{Completer, Completion, DEFAULT_COMPLETER_IDENT, NO_COMPLETER_IDENT};

const COMPLETION_VIEW_MAX_HEIGHT: i32 = 300;

#[allow(missing_docs)]
pub struct Model {
    completion: Completion,
    original_input: String,
    visible: bool,
}

/// A widget to show completions for the command entry.
#[widget]
impl Widget for CompletionView {
    fn init_view(&mut self) {
        self.add_columns(2);
    }

    fn model(_relm: &Relm<Self>, _: ()) -> Model {
        Model {
            completion: Completion::new(),
            original_input: String::new(),
            visible: false,
        }
    }

    /// Set the visibility of the view.
    pub fn set_visible(&mut self, visible: bool) {
        self.model.visible = visible;
    }

    /// Show the completion view.
    pub fn show_completion(&mut self) {
        self.unselect();
        self.scroll_to_first();
        self.model.visible = true;
    }

    fn update(&mut self, _event: ()) {
    }

    view! {
        #[name="scrolled_window"]
        gtk::ScrolledWindow {
            max_content_height: COMPLETION_VIEW_MAX_HEIGHT,
            propagate_natural_height: true,
            valign: Align::End,
            visible: self.model.visible,
            #[name="tree_view"]
            gtk::TreeView {
                can_focus: false,
                enable_search: false,
                headers_visible: false,
            }
        }
    }
}

impl CompletionView {
    /// Add a column to the tree view.
    fn add_column(&self, index: i32, foreground_index: i32, column: Column) {
        let view_column = TreeViewColumn::new();
        let cell = CellRendererText::new();
        if column == Expand {
            cell.set_property_ellipsize(EllipsizeMode::End);
            view_column.set_expand(true);
        }
        view_column.pack_start(&cell, true);
        view_column.add_attribute(&cell, "text", index);
        view_column.add_attribute(&cell, "foreground", foreground_index);
        self.tree_view.append_column(&view_column);
    }

    /// Add the specified number of columns.
    fn add_columns(&self, column_count: i32) {
        self.remove_columns();
        for i in 0 .. column_count {
            self.add_column(i, column_count + i, Expand);
        }
    }

    /// Add the specified number of columns.
    fn add_columns_from_completer(&self, completer: &Completer) {
        self.remove_columns();
        let columns = completer.columns();
        let column_count = columns.len() as i32;
        for (i, column) in columns.iter().enumerate() {
            let i = i as i32;
            self.add_column(i, column_count + i, *column);
        }
    }

    /// Adjust the columns from the completer.
    pub fn adjust_columns(&self, completer: &Completer) {
        self.add_columns_from_completer(completer);
    }

    /// Adjust the policy of the scrolled window to avoid having extra space around the tree view.
    pub fn adjust_policy<M: IsA<Object> + IsA<TreeModel>>(&self, model: &M) {
        self.tree_view.set_model(Some(model));
        let policy =
            if model.iter_n_children(None) < 2 {
                Never
            }
            else {
                Automatic
            };
        self.scrolled_window.set_policy(Never, policy);
    }

    /// Complete the result for the selection using the current completer.
    pub fn complete_result(&self, selection: &TreeSelection) -> Option<String> {
        self.model.completion.complete_result(selection)
    }

    /// Delete the current completion item.
    pub fn delete_current_completion_item(&self) {
        if let Some((model, iter)) = self.tree_view.get_selection().get_selected() {
            if let Ok(model) = model.downcast::<ListStore>() {
                self.select_next();
                model.remove(&iter);
                self.adjust_policy(&model);
            }
        }
    }

    /// Adjust the policy of the scrolled window to avoid having extra space around the tree view.
    pub fn disable_scrollbars(&self) {
        self.scrolled_window.set_policy(Never, Never);
    }

    /// Filter the completion view.
    fn filter(&mut self, command_entry_text: &str) {
        // Disable the scrollbars so that commands without completion does not
        // show the completion view.
        self.disable_scrollbars();
        let model = self.model.completion.filter(command_entry_text);
        if let Some(model) = model {
            self.adjust_policy(&model);
        }
    }

    /// Get the original input.
    pub fn original_input(&self) -> &str {
        &self.model.original_input
    }

    /// Remove all the columns.
    fn remove_columns(&self) {
        for column in &self.tree_view.get_columns() {
            self.tree_view.remove_column(column);
        }
    }

    /// Scroll to the selected row.
    fn scroll(&self, model: &TreeModel, iter: &TreeIter) {
        if let Some(path) = model.get_path(iter) {
            self.tree_view.scroll_to_cell(Some(&path), None, false, 0.0, 0.0);
        }
    }

    /// Scroll to the first row.
    pub fn scroll_to_first(&self) {
        if let Some(model) = self.tree_view.get_model() {
            if let Some(iter) = model.get_iter_first() {
                if let Some(path) = model.get_path(&iter) {
                    self.tree_view.scroll_to_cell(Some(&path), None, false, 0.0, 0.0);
                }
            }
        }
    }

    /// Select the completer based on the currently typed command.
    pub fn select_completer(&mut self, command_entry_text: &str) {
        let text = command_entry_text.trim_left();
        if let Some(space_index) = text.find(' ') {
            let command = &text[..space_index];
            self.set_completer(command, command_entry_text);
        }
        else {
            self.set_completer(DEFAULT_COMPLETER_IDENT, command_entry_text);
        }
    }

    /// Select the next item.
    /// This loops with the value that started the completion.
    pub fn select_next(&self) -> (Option<TreeSelection>, bool) {
        let mut unselect = false;
        let selection =
            if let Some(model) = self.tree_view.get_model() {
                let selection = self.tree_view.get_selection();
                if let Some((model, selected_iter)) = selection.get_selected() {
                    if model.iter_next(&selected_iter) {
                        selection.select_iter(&selected_iter);
                        self.scroll(&model, &selected_iter);
                    }
                    else {
                        self.unselect();
                        unselect = true;
                    }
                }
                else if let Some(iter) = model.get_iter_first() {
                    self.scroll(&model, &iter);
                    selection.select_iter(&iter);
                }
                Some(selection)
            }
            else {
                None
            };
        (selection, unselect)
    }

    /// Select the previous item.
    /// This loops with the value that started the completion.
    pub fn select_previous(&self) -> (Option<TreeSelection>, bool) {
        let mut unselect = false;
        let selection =
            if let Some(model) = self.tree_view.get_model() {
                let selection = self.tree_view.get_selection();
                if let Some((model, selected_iter)) = selection.get_selected() {
                    if model.iter_previous(&selected_iter) {
                        selection.select_iter(&selected_iter);
                        self.scroll(&model, &selected_iter);
                    }
                    else {
                        self.unselect();
                        unselect = true;
                    }
                }
                else if let Some(iter) = model.iter_nth_child(None, max(0, model.iter_n_children(None) - 1)) {
                    self.scroll(&model, &iter);
                    selection.select_iter(&iter);
                }
                Some(selection)
            }
            else {
                None
            };
        (selection, unselect)
    }

    /// Set the current command completer.
    pub fn set_completer(&mut self, completer: &str, command_entry_text: &str) {
        if self.model.completion.adjust_model(completer) {
            let model: Option<&ListStore> = None;
            self.tree_view.set_model(model);
        }
        {
            let completer = self.model.completion.current_completer().expect("completer should be set");
            self.adjust_columns(&**completer);
        }
        self.filter(command_entry_text);
    }

    /// Set all the completers.
    pub fn set_completers(&mut self, completers: HashMap<String, Box<Completer>>) {
        self.model.completion.set_completers(completers);
    }

    /// Set the original input.
    pub fn set_original_input(&mut self, input: &str) {
        self.model.original_input = input.to_string();
    }

    /// Unselect the item.
    pub fn unselect(&self) {
        let selection = self.tree_view.get_selection();
        selection.unselect_all();
    }

    /// Update the completions.
    pub fn update_completions(&mut self, current_mode: &str, command_entry_text: &str) {
        if current_mode == COMMAND_MODE {
            // In command mode, the completer can change when the user type.
            // For instance, after typing "set ", the completer switch to the settings
            // completer.
            // TODO: add command_entry_text in the model?
            self.select_completer(command_entry_text);
        }
        else {
            // Do not select another completer when in input mode.
            self.filter(command_entry_text);
        }
        if self.model.completion.current_completer_ident() != NO_COMPLETER_IDENT {
            self.filter(command_entry_text);
            // return Some(SetOriginalInput(text); // TODO
            self.set_original_input(command_entry_text);
        }
        self.unselect();
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::utils::Fallible;
use dom::document::AbstractDocument;
use dom::node::{ScriptView, Node, DocumentFragmentNodeTypeId};
use dom::node::{AbstractNode};
use dom::window::Window;

pub struct DocumentFragment {
    node: Node<ScriptView>,
}

impl DocumentFragment {
    /// Creates a new DocumentFragment.
    pub fn new(document: AbstractDocument) -> DocumentFragment {
        DocumentFragment {
            node: Node::new(DocumentFragmentNodeTypeId, document),
        }
    }

    pub fn Constructor(owner: @mut Window) -> Fallible<AbstractNode<ScriptView>> {
        let cx = owner.page.js_info.get_ref().js_compartment.cx.ptr;
        let fragment = @DocumentFragment::new(owner.Document());
        Ok(unsafe { Node::as_abstract_node(cx, fragment) })
    }
}
<commit_msg>auto merge of #1058 : Ms2ger/servo/get_cx-followup, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::utils::Fallible;
use dom::document::AbstractDocument;
use dom::node::{ScriptView, Node, DocumentFragmentNodeTypeId};
use dom::node::{AbstractNode};
use dom::window::Window;

pub struct DocumentFragment {
    node: Node<ScriptView>,
}

impl DocumentFragment {
    /// Creates a new DocumentFragment.
    pub fn new(document: AbstractDocument) -> DocumentFragment {
        DocumentFragment {
            node: Node::new(DocumentFragmentNodeTypeId, document),
        }
    }

    pub fn Constructor(owner: @mut Window) -> Fallible<AbstractNode<ScriptView>> {
        let cx = owner.get_cx();
        let fragment = @DocumentFragment::new(owner.Document());
        Ok(unsafe { Node::as_abstract_node(cx, fragment) })
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::BindingDeclarations::HTMLFrameElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLFrameElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLFrameElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use dom::window::Window;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLFrameElement {
    pub htmlelement: HTMLElement
}

impl HTMLFrameElementDerived for EventTarget {
    fn is_htmlframeelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLFrameElementTypeId))
    }
}

impl HTMLFrameElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLFrameElement {
        HTMLFrameElement {
            htmlelement: HTMLElement::new_inherited(HTMLFrameElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLFrameElement> {
        let element = HTMLFrameElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLFrameElementBinding::Wrap)
    }
}

pub trait HTMLFrameElementMethods {
    fn Name(&self) -> DOMString;
    fn SetName(&mut self, _name: DOMString) -> ErrorResult;
    fn Scrolling(&self) -> DOMString;
    fn SetScrolling(&mut self, _scrolling: DOMString) -> ErrorResult;
    fn Src(&self) -> DOMString;
    fn SetSrc(&mut self, _src: DOMString) -> ErrorResult;
    fn FrameBorder(&self) -> DOMString;
    fn SetFrameBorder(&mut self, _frameborder: DOMString) -> ErrorResult;
    fn LongDesc(&self) -> DOMString;
    fn SetLongDesc(&mut self, _longdesc: DOMString) -> ErrorResult;
    fn NoResize(&self) -> bool;
    fn SetNoResize(&mut self, _no_resize: bool) -> ErrorResult;
    fn GetContentDocument(&self) -> Option<Temporary<Document>>;
    fn GetContentWindow(&self) -> Option<Temporary<Window>>;
    fn MarginHeight(&self) -> DOMString;
    fn SetMarginHeight(&mut self, _height: DOMString) -> ErrorResult;
    fn MarginWidth(&self) -> DOMString;
    fn SetMarginWidth(&mut self, _height: DOMString) -> ErrorResult;
}

impl<'a> HTMLFrameElementMethods for JSRef<'a, HTMLFrameElement> {
    fn Name(&self) -> DOMString {
        "".to_owned()
    }

    fn SetName(&mut self, _name: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Scrolling(&self) -> DOMString {
        "".to_owned()
    }

    fn SetScrolling(&mut self, _scrolling: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Src(&self) -> DOMString {
        "".to_owned()
    }

    fn SetSrc(&mut self, _src: DOMString) -> ErrorResult {
        Ok(())
    }

    fn FrameBorder(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFrameBorder(&mut self, _frameborder: DOMString) -> ErrorResult {
        Ok(())
    }

    fn LongDesc(&self) -> DOMString {
        "".to_owned()
    }

    fn SetLongDesc(&mut self, _longdesc: DOMString) -> ErrorResult {
        Ok(())
    }

    fn NoResize(&self) -> bool {
        false
    }

    fn SetNoResize(&mut self, _no_resize: bool) -> ErrorResult {
        Ok(())
    }

    fn GetContentDocument(&self) -> Option<Temporary<Document>> {
        None
    }

    fn GetContentWindow(&self) -> Option<Temporary<Window>> {
        None
    }

    fn MarginHeight(&self) -> DOMString {
        "".to_owned()
    }

    fn SetMarginHeight(&mut self, _height: DOMString) -> ErrorResult {
        Ok(())
    }

    fn MarginWidth(&self) -> DOMString {
        "".to_owned()
    }

    fn SetMarginWidth(&mut self, _height: DOMString) -> ErrorResult {
        Ok(())
    }
}
<commit_msg>Remove needless '&mut self' from HTMLFrameElementMethods.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::BindingDeclarations::HTMLFrameElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLFrameElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLFrameElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use dom::window::Window;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLFrameElement {
    pub htmlelement: HTMLElement
}

impl HTMLFrameElementDerived for EventTarget {
    fn is_htmlframeelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLFrameElementTypeId))
    }
}

impl HTMLFrameElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLFrameElement {
        HTMLFrameElement {
            htmlelement: HTMLElement::new_inherited(HTMLFrameElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLFrameElement> {
        let element = HTMLFrameElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLFrameElementBinding::Wrap)
    }
}

pub trait HTMLFrameElementMethods {
    fn Name(&self) -> DOMString;
    fn SetName(&self, _name: DOMString) -> ErrorResult;
    fn Scrolling(&self) -> DOMString;
    fn SetScrolling(&self, _scrolling: DOMString) -> ErrorResult;
    fn Src(&self) -> DOMString;
    fn SetSrc(&self, _src: DOMString) -> ErrorResult;
    fn FrameBorder(&self) -> DOMString;
    fn SetFrameBorder(&self, _frameborder: DOMString) -> ErrorResult;
    fn LongDesc(&self) -> DOMString;
    fn SetLongDesc(&self, _longdesc: DOMString) -> ErrorResult;
    fn NoResize(&self) -> bool;
    fn SetNoResize(&self, _no_resize: bool) -> ErrorResult;
    fn GetContentDocument(&self) -> Option<Temporary<Document>>;
    fn GetContentWindow(&self) -> Option<Temporary<Window>>;
    fn MarginHeight(&self) -> DOMString;
    fn SetMarginHeight(&self, _height: DOMString) -> ErrorResult;
    fn MarginWidth(&self) -> DOMString;
    fn SetMarginWidth(&self, _height: DOMString) -> ErrorResult;
}

impl<'a> HTMLFrameElementMethods for JSRef<'a, HTMLFrameElement> {
    fn Name(&self) -> DOMString {
        "".to_owned()
    }

    fn SetName(&self, _name: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Scrolling(&self) -> DOMString {
        "".to_owned()
    }

    fn SetScrolling(&self, _scrolling: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Src(&self) -> DOMString {
        "".to_owned()
    }

    fn SetSrc(&self, _src: DOMString) -> ErrorResult {
        Ok(())
    }

    fn FrameBorder(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFrameBorder(&self, _frameborder: DOMString) -> ErrorResult {
        Ok(())
    }

    fn LongDesc(&self) -> DOMString {
        "".to_owned()
    }

    fn SetLongDesc(&self, _longdesc: DOMString) -> ErrorResult {
        Ok(())
    }

    fn NoResize(&self) -> bool {
        false
    }

    fn SetNoResize(&self, _no_resize: bool) -> ErrorResult {
        Ok(())
    }

    fn GetContentDocument(&self) -> Option<Temporary<Document>> {
        None
    }

    fn GetContentWindow(&self) -> Option<Temporary<Window>> {
        None
    }

    fn MarginHeight(&self) -> DOMString {
        "".to_owned()
    }

    fn SetMarginHeight(&self, _height: DOMString) -> ErrorResult {
        Ok(())
    }

    fn MarginWidth(&self) -> DOMString {
        "".to_owned()
    }

    fn SetMarginWidth(&self, _height: DOMString) -> ErrorResult {
        Ok(())
    }
}
<|endoftext|>


<commit_before>
use std::ops::{Index, IndexMut};
use std::str::FromStr;

use error::{NcclError, ErrorKind};

// top level key that contains everything is __top_level__
#[derive(Clone, Debug, PartialEq)]
pub struct Pair {
    pub key: String,
    pub value: Vec<Pair>
}

impl Pair {
    pub fn new(key: &str) -> Self {
        Pair {
            key: key.to_owned(),
            value: vec![]
        }
    }

    pub fn add(&mut self, value: &str) {
        self.value.push(Pair::new(value));
    }

    pub fn add_slice(&mut self, path: &[String]) {
        self.traverse_path(&path[0..path.len() - 1]).add(&path[path.len() - 1]);
    }

    pub fn traverse(&mut self, levels: usize) -> &mut Pair {
        if levels == 0 {
            self
        } else {
            self.value[0].traverse(levels - 1)
        }
    }

    pub fn traverse_path(&mut self, path: &[String]) -> &mut Pair {
        if path.len() == 0 {
            self
        } else {
            self.add(&path[0]);
            self.get(&path[0]).unwrap().traverse_path(&path[1..path.len()])
        }
    }

    pub fn add_pair(&mut self, pair: Pair) {
        if !self.keys().contains(&pair.key) {
            self.value.push(pair);
        } else {
            self[&pair.key].value = pair.value;
        }
    }

    pub fn has_key(&self, key: &str) -> bool {
        for item in self.value.iter() {
            if &item.key == key {
                return true;
            }
        }

        return false;
    }

    pub fn get(&mut self, value: &str) -> Result<&mut Pair, NcclError> {
        let value = value.to_owned();

        if self.value.is_empty() {
            return Err(NcclError::new(ErrorKind::KeyNotFound, &format!("Pair does not have key: {}", value), 0));
        } else {
            for item in self.value.iter_mut() {
                if item.key == value {
                    return Ok(item);
                }
            }
        }

        Err(NcclError::new(ErrorKind::KeyNotFound, &format!("Could not find key: {}", value), 0))
    }

    pub fn get_ref(&self, value: &str) -> Result<&Pair, NcclError> {
        let value_owned = value.to_owned();

        if self.value.is_empty() {
            return Ok(self);
        } else {
            for item in self.value.iter() {
                if item.key == value_owned {
                    return Ok(item);
                }
            }
        }

        Err(NcclError::new(ErrorKind::KeyNotFound, "Cound not find key", 0))
    }

    pub fn value(&self) -> Result<String, NcclError>  {
        if self.value.len() == 1 {
            Ok(self.value[0].key.clone())
        } else if self.value.len() > 1 {
            Err(NcclError::new(ErrorKind::NoValue, "Key has multiple values", 0))
        } else {
            Err(NcclError::new(ErrorKind::NoValue, "Key does not have value", 0))
        }
    }

    pub fn value_as<T>(&self) -> Result<T, NcclError> where T: FromStr {
        match self.value() {
            Ok(value) => match value.parse::<T>() {
                Ok(ok) => Ok(ok),
                Err(_) => Err(NcclError::new(ErrorKind::ParseError, "Could not parse value", 0))
            },
            Err(err) => Err(err)
        }
    }

    pub fn keys(&self) -> Vec<String> {
        self.value.clone().into_iter().map(|x| x.key).collect()
    }

    pub fn keys_as<T: FromStr>(&self) -> Result<Vec<T>, NcclError> {
        // XXX this is gross
        match self.keys().iter().map(|s| s.parse::<T>()).collect::<Result<Vec<T>, _>>() {
            Ok(ok) => Ok(ok),
            Err(_) => Err(NcclError::new(ErrorKind::FromStrError, "Could not parse keys", 0))
        }
    }
}

impl<'a> Index<&'a str> for Pair {
    type Output = Pair;
    fn index(&self, i: &str) -> &Pair {
        self.get_ref(i).unwrap()
    }
}

impl<'a> IndexMut<&'a str> for Pair {
    fn index_mut(&mut self, i: &str) -> &mut Pair {
        self.get(i).unwrap()
    }
}

<commit_msg>change behavior of add_slice, traverse_path<commit_after>
use std::ops::{Index, IndexMut};
use std::str::FromStr;

use error::{NcclError, ErrorKind};

// top level key that contains everything is __top_level__
#[derive(Clone, Debug, PartialEq)]
pub struct Pair {
    pub key: String,
    pub value: Vec<Pair>
}

impl Pair {
    pub fn new(key: &str) -> Self {
        Pair {
            key: key.to_owned(),
            value: vec![]
        }
    }

    pub fn add(&mut self, value: &str) {
        self.value.push(Pair::new(value));
    }

    pub fn add_slice(&mut self, path: &[String]) {
        let mut s = self.traverse_path(&path[0..path.len() - 1]);
        if !s.has_key(&path[path.len() - 1]) {
            s.add(&path[path.len() - 1]);
        }
    }

    pub fn traverse(&mut self, levels: usize) -> &mut Pair {
        if levels == 0 {
            self
        } else {
            self.value[0].traverse(levels - 1)
        }
    }

    pub fn traverse_path(&mut self, path: &[String]) -> &mut Pair {
        if path.len() == 0 {
            self
        } else {
            if !self.has_key(&path[0]) {
                self.add(&path[0]);
            }
            self.get(&path[0]).unwrap().traverse_path(&path[1..path.len()])
        }
    }

    pub fn add_pair(&mut self, pair: Pair) {
        if !self.keys().contains(&pair.key) {
            self.value.push(pair);
        } else {
            self[&pair.key].value = pair.value;
        }
    }

    pub fn has_key(&self, key: &str) -> bool {
        for item in self.value.iter() {
            if &item.key == key {
                return true;
            }
        }

        return false;
    }

    pub fn get(&mut self, value: &str) -> Result<&mut Pair, NcclError> {
        let value = value.to_owned();

        if self.value.is_empty() {
            return Err(NcclError::new(ErrorKind::KeyNotFound, &format!("Pair does not have key: {}", value), 0));
        } else {
            for item in self.value.iter_mut() {
                if item.key == value {
                    return Ok(item);
                }
            }
        }

        Err(NcclError::new(ErrorKind::KeyNotFound, &format!("Could not find key: {}", value), 0))
    }

    pub fn get_ref(&self, value: &str) -> Result<&Pair, NcclError> {
        let value_owned = value.to_owned();

        if self.value.is_empty() {
            return Ok(self);
        } else {
            for item in self.value.iter() {
                if item.key == value_owned {
                    return Ok(item);
                }
            }
        }

        Err(NcclError::new(ErrorKind::KeyNotFound, "Cound not find key", 0))
    }

    pub fn value(&self) -> Result<String, NcclError>  {
        if self.value.len() == 1 {
            Ok(self.value[0].key.clone())
        } else if self.value.len() > 1 {
            Err(NcclError::new(ErrorKind::NoValue, "Key has multiple values", 0))
        } else {
            Err(NcclError::new(ErrorKind::NoValue, "Key does not have value", 0))
        }
    }

    pub fn value_as<T>(&self) -> Result<T, NcclError> where T: FromStr {
        match self.value() {
            Ok(value) => match value.parse::<T>() {
                Ok(ok) => Ok(ok),
                Err(_) => Err(NcclError::new(ErrorKind::ParseError, "Could not parse value", 0))
            },
            Err(err) => Err(err)
        }
    }

    pub fn keys(&self) -> Vec<String> {
        self.value.clone().into_iter().map(|x| x.key).collect()
    }

    pub fn keys_as<T: FromStr>(&self) -> Result<Vec<T>, NcclError> {
        // XXX this is gross
        match self.keys().iter().map(|s| s.parse::<T>()).collect::<Result<Vec<T>, _>>() {
            Ok(ok) => Ok(ok),
            Err(_) => Err(NcclError::new(ErrorKind::FromStrError, "Could not parse keys", 0))
        }
    }
}

impl<'a> Index<&'a str> for Pair {
    type Output = Pair;
    fn index(&self, i: &str) -> &Pair {
        self.get_ref(i).unwrap()
    }
}

impl<'a> IndexMut<&'a str> for Pair {
    fn index_mut(&mut self, i: &str) -> &mut Pair {
        self.get(i).unwrap()
    }
}

<|endoftext|>


<commit_before>//! [Church pair](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::*;
use term::Term::*;
use term::Error::*;
use booleans::*;

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// PAIR := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// use lambda_calculus::pair::pair;
/// use lambda_calculus::arithmetic::{zero, one};
/// let pair01 = pair().app(zero()).app(one());
///
/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
/// assert_eq!(pair01.snd_ref(), Ok(&one()));
/// ```
pub fn pair() -> Term {
    abs(abs(abs(
        Var(1)
        .app(Var(3))
        .app(Var(2))
    )))
}

/// Applied to a Church-encoded pair `(a, b)` it yields `a`.
///
/// FIRST := λp.p TRUE = λ 1 TRUE
///
/// # Example
/// ```
/// use lambda_calculus::pair::{pair, first};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::normalize;
///
/// let pair_0_1 = pair().app(zero()).app(one());
///
/// assert_eq!(normalize(first().app(pair_0_1)), zero());
/// ```
pub fn first() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair `(a, b)` it yields `b`.
///
/// SECOND := λp.p FALSE = λ 1 FALSE
///
/// # Example
/// ```
/// use lambda_calculus::pair::{pair, second};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::normalize;
///
/// let pair_0_1 = pair().app(zero()).app(one());
///
/// assert_eq!(normalize(second().app(pair_0_1)), one());
/// ```
pub fn second() -> Term { abs(Var(1).app(fls())) }

impl Term {
    /// Checks whether `self` is a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert!(pair01.is_pair());
    /// ```
    pub fn is_pair(&self) -> bool {
        self.fst_ref().is_ok() && self.snd_ref().is_ok()
    }

    /// Splits a Church-encoded pair into a pair of terms, consuming `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.unpair(), Ok((zero(), one())));
    /// ```
    pub fn unpair(self) -> Result<(Term, Term), Error> {
        if let Abs(_) = self {
            if let Ok((wrapped_a, b)) = self.unabs().and_then(|t| t.unapp()) {
                Ok((try!(wrapped_a.rhs()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp() {
                Ok((try!(wrapped_a.rhs()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Splits a Church-encoded pair into a pair of references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
    /// ```
    pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
        if let Abs(_) = *self {
            if let Ok((wrapped_a, b)) = self.unabs_ref().and_then(|t| t.unapp_ref()) {
                Ok((try!(wrapped_a.rhs_ref()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp_ref() {
                Ok((try!(wrapped_a.rhs_ref()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.unpair_ref_mut(), Ok((&mut zero(), &mut one())));
    /// ```
    pub fn unpair_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        if let Abs(_) = *self {
            if let Ok((wrapped_a, b)) = self.unabs_ref_mut().and_then(|t| t.unapp_ref_mut()) {
                Ok((try!(wrapped_a.rhs_ref_mut()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp_ref_mut() {
                Ok((try!(wrapped_a.rhs_ref_mut()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Returns the first term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.fst(), Ok(zero()));
    /// ```
    pub fn fst(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).0)
    }

    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.fst_ref(), Ok(&zero()));
    /// ```
    pub fn fst_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).0)
    }

    /// Returns a mutable reference to the first term of a Church-encoded pair.
    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.fst_ref_mut(), Ok(&mut zero()));
    /// ```
    pub fn fst_ref_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_ref_mut()).0)
    }

    /// Returns the second term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.snd(), Ok(one()));
    /// ```
    pub fn snd(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).1)
    }

    /// Returns a reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.snd_ref(), Ok(&one()));
    /// ```
    pub fn snd_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).1)
    }

    /// Returns a mutable reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.snd_ref_mut(), Ok(&mut one()));
    /// ```
    pub fn snd_ref_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_ref_mut()).1)
    }
}

impl From<(Term, Term)> for Term {
    fn from((t1, t2): (Term, Term)) -> Self {
        abs(
            Var(1)
            .app(t1)
            .app(t2)
        )
    }
}

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

    #[test]
    fn pair_from_pair() {
        assert_eq!(Term::from((0.into(), 1.into())), normalize(pair().app(0.into()).app(1.into())));
    }

    #[test]
    fn pair_operations() {
        let pair_four_three = normalize(pair().app(4.into()).app(3.into()));

        assert!(pair_four_three.is_pair());

        assert_eq!(pair_four_three.fst_ref(), Ok(&4.into()));
        assert_eq!(pair_four_three.snd_ref(), Ok(&3.into()));

        let unpaired = pair_four_three.unpair();
        assert_eq!(unpaired, Ok((4.into(), 3.into())));
    }
}
<commit_msg>normalize() > beta_full() in pair.rs<commit_after>//! [Church pair](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::*;
use term::Term::*;
use term::Error::*;
use booleans::*;

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// PAIR := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// use lambda_calculus::pair::pair;
/// use lambda_calculus::arithmetic::{zero, one};
/// let pair01 = pair().app(zero()).app(one());
///
/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
/// assert_eq!(pair01.snd_ref(), Ok(&one()));
/// ```
pub fn pair() -> Term {
    abs(abs(abs(
        Var(1)
        .app(Var(3))
        .app(Var(2))
    )))
}

/// Applied to a Church-encoded pair `(a, b)` it yields `a`.
///
/// FIRST := λp.p TRUE = λ 1 TRUE
///
/// # Example
/// ```
/// use lambda_calculus::pair::{pair, first};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::beta_full;
///
/// let pair_0_1 = pair().app(zero()).app(one());
///
/// assert_eq!(beta_full(first().app(pair_0_1)), zero());
/// ```
pub fn first() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair `(a, b)` it yields `b`.
///
/// SECOND := λp.p FALSE = λ 1 FALSE
///
/// # Example
/// ```
/// use lambda_calculus::pair::{pair, second};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::beta_full;
///
/// let pair_0_1 = pair().app(zero()).app(one());
///
/// assert_eq!(beta_full(second().app(pair_0_1)), one());
/// ```
pub fn second() -> Term { abs(Var(1).app(fls())) }

impl Term {
    /// Checks whether `self` is a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert!(pair01.is_pair());
    /// ```
    pub fn is_pair(&self) -> bool {
        self.fst_ref().is_ok() && self.snd_ref().is_ok()
    }

    /// Splits a Church-encoded pair into a pair of terms, consuming `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.unpair(), Ok((zero(), one())));
    /// ```
    pub fn unpair(self) -> Result<(Term, Term), Error> {
        if let Abs(_) = self {
            if let Ok((wrapped_a, b)) = self.unabs().and_then(|t| t.unapp()) {
                Ok((try!(wrapped_a.rhs()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp() {
                Ok((try!(wrapped_a.rhs()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Splits a Church-encoded pair into a pair of references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
    /// ```
    pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
        if let Abs(_) = *self {
            if let Ok((wrapped_a, b)) = self.unabs_ref().and_then(|t| t.unapp_ref()) {
                Ok((try!(wrapped_a.rhs_ref()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp_ref() {
                Ok((try!(wrapped_a.rhs_ref()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.unpair_ref_mut(), Ok((&mut zero(), &mut one())));
    /// ```
    pub fn unpair_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        if let Abs(_) = *self {
            if let Ok((wrapped_a, b)) = self.unabs_ref_mut().and_then(|t| t.unapp_ref_mut()) {
                Ok((try!(wrapped_a.rhs_ref_mut()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp_ref_mut() {
                Ok((try!(wrapped_a.rhs_ref_mut()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Returns the first term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.fst(), Ok(zero()));
    /// ```
    pub fn fst(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).0)
    }

    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.fst_ref(), Ok(&zero()));
    /// ```
    pub fn fst_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).0)
    }

    /// Returns a mutable reference to the first term of a Church-encoded pair.
    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.fst_ref_mut(), Ok(&mut zero()));
    /// ```
    pub fn fst_ref_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_ref_mut()).0)
    }

    /// Returns the second term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.snd(), Ok(one()));
    /// ```
    pub fn snd(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).1)
    }

    /// Returns a reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.snd_ref(), Ok(&one()));
    /// ```
    pub fn snd_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).1)
    }

    /// Returns a mutable reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = pair().app(zero()).app(one());
    ///
    /// assert_eq!(pair01.snd_ref_mut(), Ok(&mut one()));
    /// ```
    pub fn snd_ref_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_ref_mut()).1)
    }
}

impl From<(Term, Term)> for Term {
    fn from((t1, t2): (Term, Term)) -> Self {
        abs(
            Var(1)
            .app(t1)
            .app(t2)
        )
    }
}

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

    #[test]
    fn pair_from_pair() {
        assert_eq!(Term::from((0.into(), 1.into())), beta_full(pair().app(0.into()).app(1.into())));
    }

    #[test]
    fn pair_operations() {
        let pair_four_three = beta_full(pair().app(4.into()).app(3.into()));

        assert!(pair_four_three.is_pair());

        assert_eq!(pair_four_three.fst_ref(), Ok(&4.into()));
        assert_eq!(pair_four_three.snd_ref(), Ok(&3.into()));

        let unpaired = pair_four_three.unpair();
        assert_eq!(unpaired, Ok((4.into(), 3.into())));
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;

use abra::schema::FieldRef;

use TermRef;

#[derive(Debug, Clone)]
pub enum BooleanQueryOp {
    PushEmpty,
    PushFull,
    PushTermDirectory(FieldRef, TermRef, u8),
    PushDeletionList,
    And,
    Or,
    AndNot,
}

#[derive(Clone, Copy, PartialEq)]
enum BooleanQueryBlockReturnType {
    Full,
    Empty,
    Sparse,
    NegatedSparse,
}

#[derive(Clone)]
enum BooleanQueryBlock {
    Leaf {
        op: BooleanQueryOp,
        return_type: BooleanQueryBlockReturnType,
    },
    Combinator {
        op: BooleanQueryOp,
        child_a: Rc<BooleanQueryBlock>,
        child_b: Rc<BooleanQueryBlock>,
        return_type: BooleanQueryBlockReturnType,
    }
}

impl BooleanQueryBlock {
    fn return_type(&self) -> BooleanQueryBlockReturnType {
        use self::BooleanQueryBlock::*;

        match *self {
            Leaf{ref op, return_type} => return_type,
            Combinator{ref op, ref child_a, ref child_b, return_type} => return_type,
        }
    }

    fn set_return_type(&mut self, new_type: BooleanQueryBlockReturnType) {
        use self::BooleanQueryBlock::*;

        match *self {
            Leaf{ref op, ref mut return_type} => *return_type = new_type,
            Combinator{ref op, ref child_a, ref child_b, ref mut return_type} => *return_type = new_type,
        }
    }

    fn build(&self, boolean_query: &mut Vec<BooleanQueryOp>) {
        use self::BooleanQueryBlock::*;

        match *self {
            Leaf{ref op, ref return_type} => {
                boolean_query.push(op.clone());
            }
            Combinator{ref op, ref child_a, ref child_b, ref return_type} => {
                child_a.build(boolean_query);
                child_b.build(boolean_query);
                boolean_query.push(op.clone());
            }
        }
    }
}

pub struct BooleanQueryBuilder {
    stack: Vec<Rc<BooleanQueryBlock>>,
}

impl BooleanQueryBuilder {
    pub fn new() -> BooleanQueryBuilder {
        BooleanQueryBuilder {
            stack: Vec::new(),
        }
    }

    pub fn push_zero(&mut self) {
        self.stack.push(Rc::new(BooleanQueryBlock::Leaf{
            op: BooleanQueryOp::PushEmpty,
            return_type: BooleanQueryBlockReturnType::Empty,
        }));
    }

    pub fn push_one(&mut self) {
        self.stack.push(Rc::new(BooleanQueryBlock::Leaf{
            op: BooleanQueryOp::PushFull,
            return_type: BooleanQueryBlockReturnType::Full,
        }));
    }

    pub fn push_op(&mut self, op: &BooleanQueryOp) {
        use search::boolean_retrieval::BooleanQueryOp::*;
        use self::BooleanQueryBlock::*;
        use self::BooleanQueryBlockReturnType::*;

        match *op {
            PushEmpty => {
                self.push_zero();
            }
            PushFull => {
                self.push_one();
            }
            PushTermDirectory(field_ref, term_ref, tag) => {
                self.stack.push(Rc::new(Leaf{
                    op: PushTermDirectory(field_ref, term_ref, tag),
                    return_type: Sparse,
                }));
            }
            PushDeletionList => {
                self.stack.push(Rc::new(Leaf{
                    op: PushDeletionList,
                    return_type: Sparse,
                }));
            }
            And => {
                let b = self.stack.pop().expect("stack underflow");
                let a = self.stack.pop().expect("stack underflow");

                match (a.return_type(), b.return_type()) {
                    // If either block is "full", replace this block with the other block
                    (Full, _) => self.stack.push(b),
                    (_, Full) => self.stack.push(a),

                    // If either block is "empty", this block will be empty too
                    (Empty, _) => self.push_zero(),
                    (_, Empty) => self.push_zero(),

                    (Sparse, Sparse) => {  // (a AND b)
                        // Intersection
                        self.stack.push(Rc::new(Combinator{
                            op: And,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (Sparse, NegatedSparse) => {  // (a AND NOT b)
                        // Exclusion
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (NegatedSparse, Sparse) => {  // (NOT a AND b)
                        // Exclusion, with operands swapped
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: b,
                            child_b: a,
                            return_type: Sparse,
                        }));
                    }

                    (NegatedSparse, NegatedSparse) => {  // (NOT a AND NOT b)
                        // Negated union (NOT (a OR b))
                        self.stack.push(Rc::new(Combinator{
                            op: Or,
                            child_a: a,
                            child_b: b,
                            return_type: NegatedSparse,
                        }));
                    }
                }
            }
            Or => {
                let b = self.stack.pop().expect("stack underflow");
                let a = self.stack.pop().expect("stack underflow");

                match (a.return_type(), b.return_type()) {
                    // If either block is "full", this block will be full too
                    (Full, _) => self.push_one(),
                    (_, Full) => self.push_one(),

                    // If either block is "empty", replace this block with the other block
                    (Empty, _) => self.stack.push(b),
                    (_, Empty) => self.stack.push(a),

                    (Sparse, Sparse) => {  // (a OR b)
                        // Union
                        self.stack.push(Rc::new(Combinator{
                            op: Or,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (Sparse, NegatedSparse) => {  // (a OR NOT b)
                        // Negated exclusion, with operands swapped (NOT (b AND NOT a))
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: b,
                            child_b: a,
                            return_type: NegatedSparse,
                        }));
                    }

                    (NegatedSparse, Sparse) => {  // (NOT a OR b)
                        // Negated exclusion (NOT (a AND NOT b))
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: a,
                            child_b: b,
                            return_type: NegatedSparse,
                        }));
                    }

                    (NegatedSparse, NegatedSparse) => {  // (NOT a OR NOT b)
                        // Negated intersection (NOT (a AND b))
                        self.stack.push(Rc::new(Combinator{
                            op: And,
                            child_a: a,
                            child_b: b,
                            return_type: NegatedSparse,
                        }));
                    }
                }
            }
            AndNot => {
                let b = self.stack.pop().expect("stack underflow");
                let a = self.stack.pop().expect("stack underflow");

                match (a.return_type(), b.return_type()) {
                    // If the right block is full, this block will be empty
                    (_, Full) => self.push_zero(),

                    // If the left block is empty, this block will be empty too
                    (Empty, _) => self.push_zero(),

                    // If the right block is empty, replace this block with the left block
                    (_, Empty) => self.stack.push(a),

                    (Full, Sparse) => {  // (ALL AND NOT b)
                        // Negation of b (NOT b)
                        let mut b_new = Rc::make_mut(&mut b.clone()).clone();
                        b_new.set_return_type(NegatedSparse);
                        self.stack.push(Rc::new(b_new));
                    }

                    (Full, NegatedSparse) => {  // (ALL AND NOT (NOT b))
                        // De-Negation of b (NOT (NOT b))
                        let mut b_new = Rc::make_mut(&mut b.clone()).clone();
                        b_new.set_return_type(Sparse);
                        self.stack.push(Rc::new(b_new));
                    }

                    (Sparse, Sparse) => {  // (a AND NOT b)
                        // Exclusion
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (Sparse, NegatedSparse) => {  // (a AND NOT (NOT b))
                        // Intersection (data AND other_data)
                        self.stack.push(Rc::new(Combinator{
                            op: And,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (NegatedSparse, Sparse) => {  // (NOT a AND NOT b)
                        // Negated union (NOT (data OR other_data))
                        self.stack.push(Rc::new(Combinator{
                            op: Or,
                            child_a: a,
                            child_b: b,
                            return_type: NegatedSparse,
                        }));
                    }

                    (NegatedSparse, NegatedSparse) => {  // (NOT a AND NOT (NOT b))
                        // Exclusion, with operands swapped (b AND NOT a)
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: b,
                            child_b: a,
                            return_type: Sparse,
                        }));
                    }
                }
            }
        }
    }

    pub fn build(&self) -> (Vec<BooleanQueryOp>, bool) {
        use self::BooleanQueryBlockReturnType::*;

        let mut boolean_query = Vec::new();

        // If the query was valid, should be exactly one item on the stack
        let root_block = self.stack.last().unwrap();
        root_block.build(&mut boolean_query);

        (boolean_query, root_block.return_type() == NegatedSparse)
    }
}
<commit_msg>Corrected a couple of method names<commit_after>use std::rc::Rc;

use abra::schema::FieldRef;

use TermRef;

#[derive(Debug, Clone)]
pub enum BooleanQueryOp {
    PushEmpty,
    PushFull,
    PushTermDirectory(FieldRef, TermRef, u8),
    PushDeletionList,
    And,
    Or,
    AndNot,
}

#[derive(Clone, Copy, PartialEq)]
enum BooleanQueryBlockReturnType {
    Full,
    Empty,
    Sparse,
    NegatedSparse,
}

#[derive(Clone)]
enum BooleanQueryBlock {
    Leaf {
        op: BooleanQueryOp,
        return_type: BooleanQueryBlockReturnType,
    },
    Combinator {
        op: BooleanQueryOp,
        child_a: Rc<BooleanQueryBlock>,
        child_b: Rc<BooleanQueryBlock>,
        return_type: BooleanQueryBlockReturnType,
    }
}

impl BooleanQueryBlock {
    fn return_type(&self) -> BooleanQueryBlockReturnType {
        use self::BooleanQueryBlock::*;

        match *self {
            Leaf{ref op, return_type} => return_type,
            Combinator{ref op, ref child_a, ref child_b, return_type} => return_type,
        }
    }

    fn set_return_type(&mut self, new_type: BooleanQueryBlockReturnType) {
        use self::BooleanQueryBlock::*;

        match *self {
            Leaf{ref op, ref mut return_type} => *return_type = new_type,
            Combinator{ref op, ref child_a, ref child_b, ref mut return_type} => *return_type = new_type,
        }
    }

    fn build(&self, boolean_query: &mut Vec<BooleanQueryOp>) {
        use self::BooleanQueryBlock::*;

        match *self {
            Leaf{ref op, ref return_type} => {
                boolean_query.push(op.clone());
            }
            Combinator{ref op, ref child_a, ref child_b, ref return_type} => {
                child_a.build(boolean_query);
                child_b.build(boolean_query);
                boolean_query.push(op.clone());
            }
        }
    }
}

pub struct BooleanQueryBuilder {
    stack: Vec<Rc<BooleanQueryBlock>>,
}

impl BooleanQueryBuilder {
    pub fn new() -> BooleanQueryBuilder {
        BooleanQueryBuilder {
            stack: Vec::new(),
        }
    }

    pub fn push_empty(&mut self) {
        self.stack.push(Rc::new(BooleanQueryBlock::Leaf{
            op: BooleanQueryOp::PushEmpty,
            return_type: BooleanQueryBlockReturnType::Empty,
        }));
    }

    pub fn push_full(&mut self) {
        self.stack.push(Rc::new(BooleanQueryBlock::Leaf{
            op: BooleanQueryOp::PushFull,
            return_type: BooleanQueryBlockReturnType::Full,
        }));
    }

    pub fn push_op(&mut self, op: &BooleanQueryOp) {
        use search::boolean_retrieval::BooleanQueryOp::*;
        use self::BooleanQueryBlock::*;
        use self::BooleanQueryBlockReturnType::*;

        match *op {
            PushEmpty => {
                self.push_empty();
            }
            PushFull => {
                self.push_full();
            }
            PushTermDirectory(field_ref, term_ref, tag) => {
                self.stack.push(Rc::new(Leaf{
                    op: PushTermDirectory(field_ref, term_ref, tag),
                    return_type: Sparse,
                }));
            }
            PushDeletionList => {
                self.stack.push(Rc::new(Leaf{
                    op: PushDeletionList,
                    return_type: Sparse,
                }));
            }
            And => {
                let b = self.stack.pop().expect("stack underflow");
                let a = self.stack.pop().expect("stack underflow");

                match (a.return_type(), b.return_type()) {
                    // If either block is "full", replace this block with the other block
                    (Full, _) => self.stack.push(b),
                    (_, Full) => self.stack.push(a),

                    // If either block is "empty", this block will be empty too
                    (Empty, _) => self.push_empty(),
                    (_, Empty) => self.push_empty(),

                    (Sparse, Sparse) => {  // (a AND b)
                        // Intersection
                        self.stack.push(Rc::new(Combinator{
                            op: And,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (Sparse, NegatedSparse) => {  // (a AND NOT b)
                        // Exclusion
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (NegatedSparse, Sparse) => {  // (NOT a AND b)
                        // Exclusion, with operands swapped
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: b,
                            child_b: a,
                            return_type: Sparse,
                        }));
                    }

                    (NegatedSparse, NegatedSparse) => {  // (NOT a AND NOT b)
                        // Negated union (NOT (a OR b))
                        self.stack.push(Rc::new(Combinator{
                            op: Or,
                            child_a: a,
                            child_b: b,
                            return_type: NegatedSparse,
                        }));
                    }
                }
            }
            Or => {
                let b = self.stack.pop().expect("stack underflow");
                let a = self.stack.pop().expect("stack underflow");

                match (a.return_type(), b.return_type()) {
                    // If either block is "full", this block will be full too
                    (Full, _) => self.push_full(),
                    (_, Full) => self.push_full(),

                    // If either block is "empty", replace this block with the other block
                    (Empty, _) => self.stack.push(b),
                    (_, Empty) => self.stack.push(a),

                    (Sparse, Sparse) => {  // (a OR b)
                        // Union
                        self.stack.push(Rc::new(Combinator{
                            op: Or,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (Sparse, NegatedSparse) => {  // (a OR NOT b)
                        // Negated exclusion, with operands swapped (NOT (b AND NOT a))
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: b,
                            child_b: a,
                            return_type: NegatedSparse,
                        }));
                    }

                    (NegatedSparse, Sparse) => {  // (NOT a OR b)
                        // Negated exclusion (NOT (a AND NOT b))
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: a,
                            child_b: b,
                            return_type: NegatedSparse,
                        }));
                    }

                    (NegatedSparse, NegatedSparse) => {  // (NOT a OR NOT b)
                        // Negated intersection (NOT (a AND b))
                        self.stack.push(Rc::new(Combinator{
                            op: And,
                            child_a: a,
                            child_b: b,
                            return_type: NegatedSparse,
                        }));
                    }
                }
            }
            AndNot => {
                let b = self.stack.pop().expect("stack underflow");
                let a = self.stack.pop().expect("stack underflow");

                match (a.return_type(), b.return_type()) {
                    // If the right block is full, this block will be empty
                    (_, Full) => self.push_empty(),

                    // If the left block is empty, this block will be empty too
                    (Empty, _) => self.push_empty(),

                    // If the right block is empty, replace this block with the left block
                    (_, Empty) => self.stack.push(a),

                    (Full, Sparse) => {  // (ALL AND NOT b)
                        // Negation of b (NOT b)
                        let mut b_new = Rc::make_mut(&mut b.clone()).clone();
                        b_new.set_return_type(NegatedSparse);
                        self.stack.push(Rc::new(b_new));
                    }

                    (Full, NegatedSparse) => {  // (ALL AND NOT (NOT b))
                        // De-Negation of b (NOT (NOT b))
                        let mut b_new = Rc::make_mut(&mut b.clone()).clone();
                        b_new.set_return_type(Sparse);
                        self.stack.push(Rc::new(b_new));
                    }

                    (Sparse, Sparse) => {  // (a AND NOT b)
                        // Exclusion
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (Sparse, NegatedSparse) => {  // (a AND NOT (NOT b))
                        // Intersection (data AND other_data)
                        self.stack.push(Rc::new(Combinator{
                            op: And,
                            child_a: a,
                            child_b: b,
                            return_type: Sparse,
                        }));
                    }

                    (NegatedSparse, Sparse) => {  // (NOT a AND NOT b)
                        // Negated union (NOT (data OR other_data))
                        self.stack.push(Rc::new(Combinator{
                            op: Or,
                            child_a: a,
                            child_b: b,
                            return_type: NegatedSparse,
                        }));
                    }

                    (NegatedSparse, NegatedSparse) => {  // (NOT a AND NOT (NOT b))
                        // Exclusion, with operands swapped (b AND NOT a)
                        self.stack.push(Rc::new(Combinator{
                            op: AndNot,
                            child_a: b,
                            child_b: a,
                            return_type: Sparse,
                        }));
                    }
                }
            }
        }
    }

    pub fn build(&self) -> (Vec<BooleanQueryOp>, bool) {
        use self::BooleanQueryBlockReturnType::*;

        let mut boolean_query = Vec::new();

        // If the query was valid, should be exactly one item on the stack
        let root_block = self.stack.last().unwrap();
        root_block.build(&mut boolean_query);

        (boolean_query, root_block.return_type() == NegatedSparse)
    }
}
<|endoftext|>