<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/. */

//! Common handling of keyboard input and state management for text input controls

use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods;
use dom::bindings::js::JSRef;
use dom::keyboardevent::KeyboardEvent;
use servo_util::str::DOMString;

use std::cmp::{min, max};
use std::default::Default;
use std::num::SignedInt;

#[deriving(Copy, PartialEq)]
enum Selection {
    Selected,
    NotSelected
}

#[jstraceable]
#[deriving(Copy)]
struct TextPoint {
    /// 0-based line number
    line: uint,
    /// 0-based column number
    index: uint,
}

/// Encapsulated state for handling keyboard input in a single or multiline text input control.
#[jstraceable]
pub struct TextInput {
    /// Current text input content, split across lines without trailing '\n'
    lines: Vec<DOMString>,
    /// Current cursor input point
    edit_point: TextPoint,
    /// Beginning of selection range with edit_point as end that can span multiple lines.
    selection_begin: Option<TextPoint>,
    /// Is this a multiline input?
    multiline: bool,
}

/// Resulting action to be taken by the owner of a text input that is handling an event.
pub enum KeyReaction {
    TriggerDefaultAction,
    DispatchInput,
    Nothing,
}

impl Default for TextPoint {
    fn default() -> TextPoint {
        TextPoint {
            line: 0,
            index: 0,
        }
    }
}

/// Control whether this control should allow multiple lines.
#[deriving(PartialEq)]
pub enum Lines {
    Single,
    Multiple,
}

/// The direction in which to delete a character.
#[deriving(PartialEq)]
enum DeleteDir {
    Forward,
    Backward
}

/// Was the keyboard event accompanied by the standard control modifier,
/// i.e. cmd on Mac OS or ctrl on other platforms.
#[cfg(target_os="macos")]
fn is_control_key(event: JSRef<KeyboardEvent>) -> bool {
    event.MetaKey() && !event.CtrlKey() && !event.AltKey()
}

#[cfg(not(target_os="macos"))]
fn is_control_key(event: JSRef<KeyboardEvent>) -> bool {
    event.CtrlKey() && !event.MetaKey() && !event.AltKey()
}

impl TextInput {
    /// Instantiate a new text input control
    pub fn new(lines: Lines, initial: DOMString) -> TextInput {
        let mut i = TextInput {
            lines: vec!(),
            edit_point: Default::default(),
            selection_begin: None,
            multiline: lines == Lines::Multiple,
        };
        i.set_content(initial);
        i
    }

    /// Remove a character at the current editing point
    fn delete_char(&mut self, dir: DeleteDir) {
        if self.selection_begin.is_none() {
            self.adjust_horizontal(if dir == DeleteDir::Forward {
                1
            } else {
                -1
            }, Selection::Selected);
        }
        self.replace_selection("".into_string());
    }

    /// Insert a character at the current editing point
    fn insert_char(&mut self, ch: char) {
        if self.selection_begin.is_none() {
            self.selection_begin = Some(self.edit_point);
        }
        self.replace_selection(ch.to_string());
    }

    fn get_sorted_selection(&self) -> (TextPoint, TextPoint) {
        let begin = self.selection_begin.unwrap();
        let end = self.edit_point;

        if begin.line < end.line || (begin.line == end.line && begin.index < end.index) {
            (begin, end)
        } else {
            (end, begin)
        }
    }

    fn replace_selection(&mut self, insert: String) {
        let (begin, end) = self.get_sorted_selection();
        self.selection_begin = None;

        let new_lines = {
            let prefix = self.lines[begin.line].slice_chars(0, begin.index);
            let suffix = self.lines[end.line].slice_chars(end.index, self.lines[end.line].char_len());
            let lines_prefix = self.lines.slice(0, begin.line);
            let lines_suffix = self.lines.slice(end.line + 1, self.lines.len());

            let mut insert_lines = if self.multiline {
                insert.as_slice().split('\n').map(|s| s.into_string()).collect()
            } else {
                vec!(insert)
            };

            let mut new_line = prefix.into_string();
            new_line.push_str(insert_lines[0].as_slice());
            insert_lines[0] = new_line;

            let last_insert_lines_index = insert_lines.len() - 1;
            self.edit_point.index = insert_lines[last_insert_lines_index].char_len();
            self.edit_point.line = begin.line + last_insert_lines_index;

            insert_lines[last_insert_lines_index].push_str(suffix);

            let mut new_lines = vec!();
            new_lines.push_all(lines_prefix);
            new_lines.push_all(insert_lines.as_slice());
            new_lines.push_all(lines_suffix);
            new_lines
        };

        self.lines = new_lines;
    }

    /// Return the length of the current line under the editing point.
    fn current_line_length(&self) -> uint {
        self.lines[self.edit_point.line].char_len()
    }

    /// Adjust the editing point position by a given of lines. The resulting column is
    /// as close to the original column position as possible.
    fn adjust_vertical(&mut self, adjust: int, select: Selection) {
        if !self.multiline {
            return;
        }

        if select == Selection::Selected {
            if self.selection_begin.is_none() {
                self.selection_begin = Some(self.edit_point);
            }
        } else {
            self.selection_begin = None;
        }

        assert!(self.edit_point.line < self.lines.len());

        let target_line: int = self.edit_point.line as int + adjust;

        if target_line < 0 {
            self.edit_point.index = 0;
            self.edit_point.line = 0;
            return;
        } else if target_line as uint >= self.lines.len() {
            self.edit_point.line = self.lines.len() - 1;
            self.edit_point.index = self.current_line_length();
            return;
        }

        self.edit_point.line = target_line as uint;
        self.edit_point.index = min(self.current_line_length(), self.edit_point.index);
    }

    /// Adjust the editing point position by a given number of columns. If the adjustment
    /// requested is larger than is available in the current line, the editing point is
    /// adjusted vertically and the process repeats with the remaining adjustment requested.
    fn adjust_horizontal(&mut self, adjust: int, select: Selection) {
        if select == Selection::Selected {
            if self.selection_begin.is_none() {
                self.selection_begin = Some(self.edit_point);
            }
        } else {
            if self.selection_begin.is_some() {
                let (begin, end) = self.get_sorted_selection();
                self.edit_point = if adjust < 0 {begin} else {end};
                self.selection_begin = None;
                return
            }
        }

        if adjust < 0 {
            let remaining = self.edit_point.index;
            if adjust.abs() as uint > remaining && self.edit_point.line > 0 {
                self.adjust_vertical(-1, select);
                self.edit_point.index = self.current_line_length();
                self.adjust_horizontal(adjust + remaining as int + 1, select);
            } else {
                self.edit_point.index = max(0, self.edit_point.index as int + adjust) as uint;
            }
        } else {
            let remaining = self.current_line_length() - self.edit_point.index;
            if adjust as uint > remaining && self.lines.len() > self.edit_point.line + 1 {
                self.adjust_vertical(1, select);
                self.edit_point.index = 0;
                // one shift is consumed by the change of line, hence the -1
                self.adjust_horizontal(adjust - remaining as int - 1, select);
            } else {
                self.edit_point.index = min(self.current_line_length(),
                                            self.edit_point.index + adjust as uint);
            }
        }
    }

    /// Deal with a newline input.
    fn handle_return(&mut self) -> KeyReaction {
        if !self.multiline {
            return KeyReaction::TriggerDefaultAction;
        }
        self.insert_char('\n');
        return KeyReaction::DispatchInput;
    }

    /// Select all text in the input control.
    fn select_all(&mut self) {
        self.selection_begin = Some(TextPoint {
            line: 0,
            index: 0,
        });
        let last_line = self.lines.len() - 1;
        self.edit_point.line = last_line;
        self.edit_point.index = self.lines[last_line].char_len();
    }

    /// Process a given `KeyboardEvent` and return an action for the caller to execute.
    pub fn handle_keydown(&mut self, event: JSRef<KeyboardEvent>) -> KeyReaction {
        //A simple way to convert an event to a selection
        fn maybe_select(event: JSRef<KeyboardEvent>) -> Selection {
            if event.ShiftKey() {
                return Selection::Selected
            }
            return Selection::NotSelected
        }
        match event.Key().as_slice() {
           "a" if is_control_key(event) => {
                self.select_all();
                KeyReaction::Nothing
            },
            // printable characters have single-character key values
            c if c.len() == 1 => {
                self.insert_char(c.char_at(0));
                return KeyReaction::DispatchInput;
            }
            "Space" => {
                self.insert_char(' ');
                KeyReaction::DispatchInput
            }
            "Delete" => {
                self.delete_char(DeleteDir::Forward);
                KeyReaction::DispatchInput
            }
            "Backspace" => {
                self.delete_char(DeleteDir::Backward);
                KeyReaction::DispatchInput
            }
            "ArrowLeft" => {
                self.adjust_horizontal(-1, maybe_select(event));
                KeyReaction::Nothing
            }
            "ArrowRight" => {
                self.adjust_horizontal(1, maybe_select(event));
                KeyReaction::Nothing
            }
            "ArrowUp" => {
                self.adjust_vertical(-1, maybe_select(event));
                KeyReaction::Nothing
            }
            "ArrowDown" => {
                self.adjust_vertical(1, maybe_select(event));
                KeyReaction::Nothing
            }
            "Enter" => self.handle_return(),
            "Home" => {
                self.edit_point.index = 0;
                KeyReaction::Nothing
            }
            "End" => {
                self.edit_point.index = self.current_line_length();
                KeyReaction::Nothing
            }
            "PageUp" => {
                self.adjust_vertical(-28, maybe_select(event));
                KeyReaction::Nothing
            }
            "PageDown" => {
                self.adjust_vertical(28, maybe_select(event));
                KeyReaction::Nothing
            }
            "Tab" => KeyReaction::TriggerDefaultAction,
            _ => KeyReaction::Nothing,
        }
    }

    /// Get the current contents of the text input. Multiple lines are joined by \n.
    pub fn get_content(&self) -> DOMString {
        let mut content = "".into_string();
        for (i, line) in self.lines.iter().enumerate() {
            content.push_str(line.as_slice());
            if i < self.lines.len() - 1 {
                content.push('\n');
            }
        }
        content
    }

    /// Set the current contents of the text input. If this is control supports multiple lines,
    /// any \n encountered will be stripped and force a new logical line.
    pub fn set_content(&mut self, content: DOMString) {
        self.lines = if self.multiline {
            content.as_slice().split('\n').map(|s| s.into_string()).collect()
        } else {
            vec!(content)
        };
        self.edit_point.line = min(self.edit_point.line, self.lines.len() - 1);

        if self.current_line_length() == 0 {
            self.edit_point.index = 0;
        }
        else {
            self.edit_point.index = min(self.edit_point.index, self.current_line_length() - 1);
        }
    }
}
<commit_msg>auto merge of #4569 : donaldpipowitch/servo/add-unit-tests-for-textinput, 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/. */

//! Common handling of keyboard input and state management for text input controls

use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods;
use dom::bindings::js::JSRef;
use dom::keyboardevent::KeyboardEvent;
use servo_util::str::DOMString;

use std::cmp::{min, max};
use std::default::Default;
use std::num::SignedInt;

#[deriving(Copy, PartialEq)]
enum Selection {
    Selected,
    NotSelected
}

#[jstraceable]
#[deriving(Copy)]
struct TextPoint {
    /// 0-based line number
    line: uint,
    /// 0-based column number
    index: uint,
}

/// Encapsulated state for handling keyboard input in a single or multiline text input control.
#[jstraceable]
pub struct TextInput {
    /// Current text input content, split across lines without trailing '\n'
    lines: Vec<DOMString>,
    /// Current cursor input point
    edit_point: TextPoint,
    /// Beginning of selection range with edit_point as end that can span multiple lines.
    selection_begin: Option<TextPoint>,
    /// Is this a multiline input?
    multiline: bool,
}

/// Resulting action to be taken by the owner of a text input that is handling an event.
pub enum KeyReaction {
    TriggerDefaultAction,
    DispatchInput,
    Nothing,
}

impl Default for TextPoint {
    fn default() -> TextPoint {
        TextPoint {
            line: 0,
            index: 0,
        }
    }
}

/// Control whether this control should allow multiple lines.
#[deriving(PartialEq)]
pub enum Lines {
    Single,
    Multiple,
}

/// The direction in which to delete a character.
#[deriving(PartialEq)]
enum DeleteDir {
    Forward,
    Backward
}

/// Was the keyboard event accompanied by the standard control modifier,
/// i.e. cmd on Mac OS or ctrl on other platforms.
#[cfg(target_os="macos")]
fn is_control_key(event: JSRef<KeyboardEvent>) -> bool {
    event.MetaKey() && !event.CtrlKey() && !event.AltKey()
}

#[cfg(not(target_os="macos"))]
fn is_control_key(event: JSRef<KeyboardEvent>) -> bool {
    event.CtrlKey() && !event.MetaKey() && !event.AltKey()
}

impl TextInput {
    /// Instantiate a new text input control
    pub fn new(lines: Lines, initial: DOMString) -> TextInput {
        let mut i = TextInput {
            lines: vec!(),
            edit_point: Default::default(),
            selection_begin: None,
            multiline: lines == Lines::Multiple,
        };
        i.set_content(initial);
        i
    }

    /// Remove a character at the current editing point
    fn delete_char(&mut self, dir: DeleteDir) {
        if self.selection_begin.is_none() {
            self.adjust_horizontal(if dir == DeleteDir::Forward {
                1
            } else {
                -1
            }, Selection::Selected);
        }
        self.replace_selection("".into_string());
    }

    /// Insert a character at the current editing point
    fn insert_char(&mut self, ch: char) {
        if self.selection_begin.is_none() {
            self.selection_begin = Some(self.edit_point);
        }
        self.replace_selection(ch.to_string());
    }

    fn get_sorted_selection(&self) -> (TextPoint, TextPoint) {
        let begin = self.selection_begin.unwrap();
        let end = self.edit_point;

        if begin.line < end.line || (begin.line == end.line && begin.index < end.index) {
            (begin, end)
        } else {
            (end, begin)
        }
    }

    fn replace_selection(&mut self, insert: String) {
        let (begin, end) = self.get_sorted_selection();
        self.clear_selection();

        let new_lines = {
            let prefix = self.lines[begin.line].slice_chars(0, begin.index);
            let suffix = self.lines[end.line].slice_chars(end.index, self.lines[end.line].char_len());
            let lines_prefix = self.lines.slice(0, begin.line);
            let lines_suffix = self.lines.slice(end.line + 1, self.lines.len());

            let mut insert_lines = if self.multiline {
                insert.as_slice().split('\n').map(|s| s.into_string()).collect()
            } else {
                vec!(insert)
            };

            let mut new_line = prefix.into_string();
            new_line.push_str(insert_lines[0].as_slice());
            insert_lines[0] = new_line;

            let last_insert_lines_index = insert_lines.len() - 1;
            self.edit_point.index = insert_lines[last_insert_lines_index].char_len();
            self.edit_point.line = begin.line + last_insert_lines_index;

            insert_lines[last_insert_lines_index].push_str(suffix);

            let mut new_lines = vec!();
            new_lines.push_all(lines_prefix);
            new_lines.push_all(insert_lines.as_slice());
            new_lines.push_all(lines_suffix);
            new_lines
        };

        self.lines = new_lines;
    }

    /// Return the length of the current line under the editing point.
    fn current_line_length(&self) -> uint {
        self.lines[self.edit_point.line].char_len()
    }

    /// Adjust the editing point position by a given of lines. The resulting column is
    /// as close to the original column position as possible.
    fn adjust_vertical(&mut self, adjust: int, select: Selection) {
        if !self.multiline {
            return;
        }

        if select == Selection::Selected {
            if self.selection_begin.is_none() {
                self.selection_begin = Some(self.edit_point);
            }
        } else {
            self.clear_selection();
        }

        assert!(self.edit_point.line < self.lines.len());

        let target_line: int = self.edit_point.line as int + adjust;

        if target_line < 0 {
            self.edit_point.index = 0;
            self.edit_point.line = 0;
            return;
        } else if target_line as uint >= self.lines.len() {
            self.edit_point.line = self.lines.len() - 1;
            self.edit_point.index = self.current_line_length();
            return;
        }

        self.edit_point.line = target_line as uint;
        self.edit_point.index = min(self.current_line_length(), self.edit_point.index);
    }

    /// Adjust the editing point position by a given number of columns. If the adjustment
    /// requested is larger than is available in the current line, the editing point is
    /// adjusted vertically and the process repeats with the remaining adjustment requested.
    fn adjust_horizontal(&mut self, adjust: int, select: Selection) {
        if select == Selection::Selected {
            if self.selection_begin.is_none() {
                self.selection_begin = Some(self.edit_point);
            }
        } else {
            if self.selection_begin.is_some() {
                let (begin, end) = self.get_sorted_selection();
                self.edit_point = if adjust < 0 {begin} else {end};
                self.clear_selection();
                return
            }
        }

        if adjust < 0 {
            let remaining = self.edit_point.index;
            if adjust.abs() as uint > remaining && self.edit_point.line > 0 {
                self.adjust_vertical(-1, select);
                self.edit_point.index = self.current_line_length();
                self.adjust_horizontal(adjust + remaining as int + 1, select);
            } else {
                self.edit_point.index = max(0, self.edit_point.index as int + adjust) as uint;
            }
        } else {
            let remaining = self.current_line_length() - self.edit_point.index;
            if adjust as uint > remaining && self.lines.len() > self.edit_point.line + 1 {
                self.adjust_vertical(1, select);
                self.edit_point.index = 0;
                // one shift is consumed by the change of line, hence the -1
                self.adjust_horizontal(adjust - remaining as int - 1, select);
            } else {
                self.edit_point.index = min(self.current_line_length(),
                                            self.edit_point.index + adjust as uint);
            }
        }
    }

    /// Deal with a newline input.
    fn handle_return(&mut self) -> KeyReaction {
        if !self.multiline {
            return KeyReaction::TriggerDefaultAction;
        }
        self.insert_char('\n');
        return KeyReaction::DispatchInput;
    }

    /// Select all text in the input control.
    fn select_all(&mut self) {
        self.selection_begin = Some(TextPoint {
            line: 0,
            index: 0,
        });
        let last_line = self.lines.len() - 1;
        self.edit_point.line = last_line;
        self.edit_point.index = self.lines[last_line].char_len();
    }

    /// Remove the current selection.
    fn clear_selection(&mut self) {
        self.selection_begin = None;
    }

    /// Process a given `KeyboardEvent` and return an action for the caller to execute.
    pub fn handle_keydown(&mut self, event: JSRef<KeyboardEvent>) -> KeyReaction {
        //A simple way to convert an event to a selection
        fn maybe_select(event: JSRef<KeyboardEvent>) -> Selection {
            if event.ShiftKey() {
                return Selection::Selected
            }
            return Selection::NotSelected
        }
        match event.Key().as_slice() {
           "a" if is_control_key(event) => {
                self.select_all();
                KeyReaction::Nothing
            },
            // printable characters have single-character key values
            c if c.len() == 1 => {
                self.insert_char(c.char_at(0));
                return KeyReaction::DispatchInput;
            }
            "Space" => {
                self.insert_char(' ');
                KeyReaction::DispatchInput
            }
            "Delete" => {
                self.delete_char(DeleteDir::Forward);
                KeyReaction::DispatchInput
            }
            "Backspace" => {
                self.delete_char(DeleteDir::Backward);
                KeyReaction::DispatchInput
            }
            "ArrowLeft" => {
                self.adjust_horizontal(-1, maybe_select(event));
                KeyReaction::Nothing
            }
            "ArrowRight" => {
                self.adjust_horizontal(1, maybe_select(event));
                KeyReaction::Nothing
            }
            "ArrowUp" => {
                self.adjust_vertical(-1, maybe_select(event));
                KeyReaction::Nothing
            }
            "ArrowDown" => {
                self.adjust_vertical(1, maybe_select(event));
                KeyReaction::Nothing
            }
            "Enter" => self.handle_return(),
            "Home" => {
                self.edit_point.index = 0;
                KeyReaction::Nothing
            }
            "End" => {
                self.edit_point.index = self.current_line_length();
                KeyReaction::Nothing
            }
            "PageUp" => {
                self.adjust_vertical(-28, maybe_select(event));
                KeyReaction::Nothing
            }
            "PageDown" => {
                self.adjust_vertical(28, maybe_select(event));
                KeyReaction::Nothing
            }
            "Tab" => KeyReaction::TriggerDefaultAction,
            _ => KeyReaction::Nothing,
        }
    }

    /// Get the current contents of the text input. Multiple lines are joined by \n.
    pub fn get_content(&self) -> DOMString {
        let mut content = "".into_string();
        for (i, line) in self.lines.iter().enumerate() {
            content.push_str(line.as_slice());
            if i < self.lines.len() - 1 {
                content.push('\n');
            }
        }
        content
    }

    /// Set the current contents of the text input. If this is control supports multiple lines,
    /// any \n encountered will be stripped and force a new logical line.
    pub fn set_content(&mut self, content: DOMString) {
        self.lines = if self.multiline {
            content.as_slice().split('\n').map(|s| s.into_string()).collect()
        } else {
            vec!(content)
        };
        self.edit_point.line = min(self.edit_point.line, self.lines.len() - 1);

        if self.current_line_length() == 0 {
            self.edit_point.index = 0;
        }
        else {
            self.edit_point.index = min(self.edit_point.index, self.current_line_length() - 1);
        }
    }
}

#[test]
fn test_textinput_delete_char() {
    let mut textinput = TextInput::new(Lines::Single, "abcdefg".into_string());
    textinput.adjust_horizontal(2, Selection::NotSelected);
    textinput.delete_char(DeleteDir::Backward);
    assert_eq!(textinput.get_content().as_slice(), "acdefg");

    textinput.delete_char(DeleteDir::Forward);
    assert_eq!(textinput.get_content().as_slice(), "adefg");

    textinput.adjust_horizontal(2, Selection::Selected);
    textinput.delete_char(DeleteDir::Forward);
    assert_eq!(textinput.get_content().as_slice(), "afg");
}

#[test]
fn test_textinput_insert_char() {
    let mut textinput = TextInput::new(Lines::Single, "abcdefg".into_string());
    textinput.adjust_horizontal(2, Selection::NotSelected);
    textinput.insert_char('a');
    assert_eq!(textinput.get_content().as_slice(), "abacdefg");

    textinput.adjust_horizontal(2, Selection::Selected);
    textinput.insert_char('b');
    assert_eq!(textinput.get_content().as_slice(), "ababefg");
}

#[test]
fn test_textinput_get_sorted_selection() {
    let mut textinput = TextInput::new(Lines::Single, "abcdefg".into_string());
    textinput.adjust_horizontal(2, Selection::NotSelected);
    textinput.adjust_horizontal(2, Selection::Selected);
    let (begin, end) = textinput.get_sorted_selection();
    assert_eq!(begin.index, 2);
    assert_eq!(end.index, 4);

    textinput.clear_selection();

    textinput.adjust_horizontal(-2, Selection::Selected);
    let (begin, end) = textinput.get_sorted_selection();
    assert_eq!(begin.index, 2);
    assert_eq!(end.index, 4);
}

#[test]
fn test_textinput_replace_selection() {
    let mut textinput = TextInput::new(Lines::Single, "abcdefg".into_string());
    textinput.adjust_horizontal(2, Selection::NotSelected);
    textinput.adjust_horizontal(2, Selection::Selected);

    textinput.replace_selection("xyz".into_string());
    assert_eq!(textinput.get_content().as_slice(), "abxyzefg");
}

#[test]
fn test_textinput_current_line_length() {
    let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".into_string());
    assert_eq!(textinput.current_line_length(), 3);

    textinput.adjust_vertical(1, Selection::NotSelected);
    assert_eq!(textinput.current_line_length(), 2);

    textinput.adjust_vertical(1, Selection::NotSelected);
    assert_eq!(textinput.current_line_length(), 1);
}

#[test]
fn test_textinput_adjust_vertical() {
    let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".into_string());
    textinput.adjust_horizontal(3, Selection::NotSelected);
    textinput.adjust_vertical(1, Selection::NotSelected);
    assert_eq!(textinput.edit_point.line, 1);
    assert_eq!(textinput.edit_point.index, 2);

    textinput.adjust_vertical(-1, Selection::NotSelected);
    assert_eq!(textinput.edit_point.line, 0);
    assert_eq!(textinput.edit_point.index, 2);

    textinput.adjust_vertical(2, Selection::NotSelected);
    assert_eq!(textinput.edit_point.line, 2);
    assert_eq!(textinput.edit_point.index, 1);
}

#[test]
fn test_textinput_adjust_horizontal() {
    let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".into_string());
    textinput.adjust_horizontal(4, Selection::NotSelected);
    assert_eq!(textinput.edit_point.line, 1);
    assert_eq!(textinput.edit_point.index, 0);

    textinput.adjust_horizontal(1, Selection::NotSelected);
    assert_eq!(textinput.edit_point.line, 1);
    assert_eq!(textinput.edit_point.index, 1);

    textinput.adjust_horizontal(2, Selection::NotSelected);
    assert_eq!(textinput.edit_point.line, 2);
    assert_eq!(textinput.edit_point.index, 0);

    textinput.adjust_horizontal(-1, Selection::NotSelected);
    assert_eq!(textinput.edit_point.line, 1);
    assert_eq!(textinput.edit_point.index, 2);
}

#[test]
fn test_textinput_handle_return() {
    let mut single_line_textinput = TextInput::new(Lines::Single, "abcdef".into_string());
    single_line_textinput.adjust_horizontal(3, Selection::NotSelected);
    single_line_textinput.handle_return();
    assert_eq!(single_line_textinput.get_content().as_slice(), "abcdef");

    let mut multi_line_textinput = TextInput::new(Lines::Multiple, "abcdef".into_string());
    multi_line_textinput.adjust_horizontal(3, Selection::NotSelected);
    multi_line_textinput.handle_return();
    assert_eq!(multi_line_textinput.get_content().as_slice(), "abc\ndef");
}

#[test]
fn test_textinput_select_all() {
    let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".into_string());
    assert_eq!(textinput.edit_point.line, 0);
    assert_eq!(textinput.edit_point.index, 0);

    textinput.select_all();
    assert_eq!(textinput.edit_point.line, 2);
    assert_eq!(textinput.edit_point.index, 1);
}

#[test]
fn test_textinput_get_content() {
    let single_line_textinput = TextInput::new(Lines::Single, "abcdefg".into_string());
    assert_eq!(single_line_textinput.get_content().as_slice(), "abcdefg");

    let multi_line_textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".into_string());
    assert_eq!(multi_line_textinput.get_content().as_slice(), "abc\nde\nf");
}

#[test]
fn test_textinput_set_content() {
    let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".into_string());
    assert_eq!(textinput.get_content().as_slice(), "abc\nde\nf");

    textinput.set_content("abc\nf".into_string());
    assert_eq!(textinput.get_content().as_slice(), "abc\nf");

    assert_eq!(textinput.edit_point.line, 0);
    assert_eq!(textinput.edit_point.index, 0);
    textinput.adjust_horizontal(3, Selection::Selected);
    assert_eq!(textinput.edit_point.line, 0);
    assert_eq!(textinput.edit_point.index, 3);
    textinput.set_content("de".into_string());
    assert_eq!(textinput.get_content().as_slice(), "de");
    assert_eq!(textinput.edit_point.line, 0);
    // FIXME: https://github.com/servo/servo/issues/4622.
    assert_eq!(textinput.edit_point.index, 1);
}

<|endoftext|>


<commit_before><commit_msg>implement RNG (device)<commit_after>extern crate rand;

use rand::{Rng, OsRng};

fn main() {
    // becuase `OsRng` opens files, it may fail
    let mut rng = OsRng::new().unwrap();

    println!("{}", rng.gen::<u32>());
}
<|endoftext|>


<commit_before><commit_msg>Add concept of a session.<commit_after>use rusqlite::Connection;
use rusqlite::Error;

#[derive(Debug)]
pub struct Session {
    pub id: i32,
    pub uuid: String,
}

pub fn table_create_session(conn: &Connection) -> &Connection {
    conn.execute("CREATE TABLE WHENENV_SESSION (
                    id              INTEGER PRIMARY KEY ASC,
                    uuid            TEXT NOT NULL UNIQUE
                  )", &[]).unwrap();
    return conn;
}

pub fn insert_session(conn: &Connection, uuid: String) -> Result<i32, &'static str> {

    let session = Session {
        id: 0,
        uuid: uuid,
    };
    let mut found = 0;
    let dir_instance = conn.execute("INSERT INTO WHENENV_SESSION (uuid)
                 VALUES (?1)",
                 &[&session.uuid]);
    if dir_instance.is_err() {

        return Err("ssss");
    }
    dir_instance.unwrap();
    return Ok(0);
}

pub fn list_session(conn: &Connection)-> Vec<Session> {
    let mut stmt = conn.prepare("SELECT id, uuid FROM WHENENV_SESSION").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        Session {
            id: row.get(0),
            uuid: row.get(1),
        }
    });
    let mut items = Vec::<Session>::new();
    if wraped_fs_file_iter.is_err() {
        return items;
    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_session_by_uuid(conn: &Connection, uuid: &String, pk: &mut i32) -> Result<i32, &'static str>{
    let mut stmt = conn.prepare("SELECT id, uuid  FROM WHENENV_SESSION WHERE uuid = ?1").unwrap();
    let insert_session_iter = stmt.query_map(&[uuid], |row| {
        Session {
            id: row.get(0),
            uuid: row.get(1),
        }
    });
    if insert_session_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = insert_session_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill= person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}

<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate hamcrest;
extern crate cargo;

use std::collections::HashMap;

use hamcrest::{assert_that, equal_to, contains, not};

use cargo::core::source::{SourceId, GitReference};
use cargo::core::dependency::Kind::{self, Development};
use cargo::core::{Dependency, PackageId, Summary, Registry};
use cargo::util::{CargoResult, ToUrl};
use cargo::core::resolver::{self, Method};

fn resolve(pkg: PackageId, deps: Vec<Dependency>, registry: &[Summary])
    -> CargoResult<Vec<PackageId>>
{
    struct MyRegistry<'a>(&'a [Summary]);
    impl<'a> Registry for MyRegistry<'a> {
        fn query(&mut self,
                 dep: &Dependency,
                 f: &mut FnMut(Summary)) -> CargoResult<()> {
            for summary in self.0.iter() {
                if dep.matches(summary) {
                    f(summary.clone());
                }
            }
            Ok(())
        }
    }
    let mut registry = MyRegistry(registry);
    let summary = Summary::new(pkg.clone(), deps, HashMap::new()).unwrap();
    let method = Method::Everything;
    let resolve = resolver::resolve(&[(summary, method)], &[], &mut registry)?;
    let res = resolve.iter().cloned().collect();
    Ok(res)
}

trait ToDep {
    fn to_dep(self) -> Dependency;
}

impl ToDep for &'static str {
    fn to_dep(self) -> Dependency {
        let url = "http://example.com".to_url().unwrap();
        let source_id = SourceId::for_registry(&url);
        Dependency::parse_no_deprecated(self, Some("1.0.0"), &source_id).unwrap()
    }
}

impl ToDep for Dependency {
    fn to_dep(self) -> Dependency {
        self
    }
}

trait ToPkgId {
    fn to_pkgid(&self) -> PackageId;
}

impl ToPkgId for &'static str {
    fn to_pkgid(&self) -> PackageId {
        PackageId::new(*self, "1.0.0", &registry_loc()).unwrap()
    }
}

impl ToPkgId for (&'static str, &'static str) {
    fn to_pkgid(&self) -> PackageId {
        let (name, vers) = *self;
        PackageId::new(name, vers, &registry_loc()).unwrap()
    }
}

macro_rules! pkg {
    ($pkgid:expr => [$($deps:expr),+]) => ({
        let d: Vec<Dependency> = vec![$($deps.to_dep()),+];

        Summary::new($pkgid.to_pkgid(), d, HashMap::new()).unwrap()
    });

    ($pkgid:expr) => (
        Summary::new($pkgid.to_pkgid(), Vec::new(), HashMap::new()).unwrap()
    )
}

fn registry_loc() -> SourceId {
    let remote = "http://example.com".to_url().unwrap();
    SourceId::for_registry(&remote)
}

fn pkg(name: &str) -> Summary {
    Summary::new(pkg_id(name), Vec::new(), HashMap::new()).unwrap()
}

fn pkg_id(name: &str) -> PackageId {
    PackageId::new(name, "1.0.0", &registry_loc()).unwrap()
}

fn pkg_id_loc(name: &str, loc: &str) -> PackageId {
    let remote = loc.to_url();
    let master = GitReference::Branch("master".to_string());
    let source_id = SourceId::for_git(&remote.unwrap(), master);

    PackageId::new(name, "1.0.0", &source_id).unwrap()
}

fn pkg_loc(name: &str, loc: &str) -> Summary {
    Summary::new(pkg_id_loc(name, loc), Vec::new(), HashMap::new()).unwrap()
}

fn dep(name: &str) -> Dependency { dep_req(name, "1.0.0") }
fn dep_req(name: &str, req: &str) -> Dependency {
    let url = "http://example.com".to_url().unwrap();
    let source_id = SourceId::for_registry(&url);
    Dependency::parse_no_deprecated(name, Some(req), &source_id).unwrap()
}

fn dep_loc(name: &str, location: &str) -> Dependency {
    let url = location.to_url().unwrap();
    let master = GitReference::Branch("master".to_string());
    let source_id = SourceId::for_git(&url, master);
    Dependency::parse_no_deprecated(name, Some("1.0.0"), &source_id).unwrap()
}
fn dep_kind(name: &str, kind: Kind) -> Dependency {
    dep(name).set_kind(kind).clone()
}

fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
    pkgs
}

fn names<P: ToPkgId>(names: &[P]) -> Vec<PackageId> {
    names.iter().map(|name| name.to_pkgid()).collect()
}

fn loc_names(names: &[(&'static str, &'static str)]) -> Vec<PackageId> {
    names.iter()
        .map(|&(name, loc)| pkg_id_loc(name, loc)).collect()
}

#[test]
fn test_resolving_empty_dependency_list() {
    let res = resolve(pkg_id("root"), Vec::new(),
                      &mut registry(vec![])).unwrap();

    assert_that(&res, equal_to(&names(&["root"])));
}

#[test]
fn test_resolving_only_package() {
    let mut reg = registry(vec![pkg("foo")]);
    let res = resolve(pkg_id("root"), vec![dep("foo")], &mut reg);

    assert_that(&res.unwrap(), contains(names(&["root", "foo"])).exactly());
}

#[test]
fn test_resolving_one_dep() {
    let mut reg = registry(vec![pkg("foo"), pkg("bar")]);
    let res = resolve(pkg_id("root"), vec![dep("foo")], &mut reg);

    assert_that(&res.unwrap(), contains(names(&["root", "foo"])).exactly());
}

#[test]
fn test_resolving_multiple_deps() {
    let mut reg = registry(vec![pkg!("foo"), pkg!("bar"), pkg!("baz")]);
    let res = resolve(pkg_id("root"), vec![dep("foo"), dep("baz")],
                      &mut reg).unwrap();

    assert_that(&res, contains(names(&["root", "foo", "baz"])).exactly());
}

#[test]
fn test_resolving_transitive_deps() {
    let mut reg = registry(vec![pkg!("foo"), pkg!("bar" => ["foo"])]);
    let res = resolve(pkg_id("root"), vec![dep("bar")], &mut reg).unwrap();

    assert_that(&res, contains(names(&["root", "foo", "bar"])));
}

#[test]
fn test_resolving_common_transitive_deps() {
    let mut reg = registry(vec![pkg!("foo" => ["bar"]), pkg!("bar")]);
    let res = resolve(pkg_id("root"), vec![dep("foo"), dep("bar")],
                      &mut reg).unwrap();

    assert_that(&res, contains(names(&["root", "foo", "bar"])));
}

#[test]
fn test_resolving_with_same_name() {
    let list = vec![pkg_loc("foo", "http://first.example.com"),
                    pkg_loc("bar", "http://second.example.com")];

    let mut reg = registry(list);
    let res = resolve(pkg_id("root"),
                      vec![dep_loc("foo", "http://first.example.com"),
                           dep_loc("bar", "http://second.example.com")],
                      &mut reg);

    let mut names = loc_names(&[("foo", "http://first.example.com"),
                                ("bar", "http://second.example.com")]);

    names.push(pkg_id("root"));

    assert_that(&res.unwrap(), contains(names).exactly());
}

#[test]
fn test_resolving_with_dev_deps() {
    let mut reg = registry(vec![
        pkg!("foo" => ["bar", dep_kind("baz", Development)]),
        pkg!("baz" => ["bat", dep_kind("bam", Development)]),
        pkg!("bar"),
        pkg!("bat")
    ]);

    let res = resolve(pkg_id("root"),
                      vec![dep("foo"), dep_kind("baz", Development)],
                      &mut reg).unwrap();

    assert_that(&res, contains(names(&["root", "foo", "bar", "baz"])));
}

#[test]
fn resolving_with_many_versions() {
    let mut reg = registry(vec![
        pkg!(("foo", "1.0.1")),
        pkg!(("foo", "1.0.2")),
    ]);

    let res = resolve(pkg_id("root"), vec![dep("foo")], &mut reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.2")])));
}

#[test]
fn resolving_with_specific_version() {
    let mut reg = registry(vec![
        pkg!(("foo", "1.0.1")),
        pkg!(("foo", "1.0.2")),
    ]);

    let res = resolve(pkg_id("root"), vec![dep_req("foo", "=1.0.1")],
                      &mut reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.1")])));
}

#[test]
fn test_resolving_maximum_version_with_transitive_deps() {
    let mut reg = registry(vec![
        pkg!(("util", "1.2.2")),
        pkg!(("util", "1.0.0")),
        pkg!(("util", "1.1.1")),
        pkg!("foo" => [dep_req("util", "1.0.0")]),
        pkg!("bar" => [dep_req("util", ">=1.0.1")]),
    ]);

    let res = resolve(pkg_id("root"), vec![dep_req("foo", "1.0.0"), dep_req("bar", "1.0.0")],
                      &mut reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.0"),
                                       ("bar", "1.0.0"),
                                       ("util", "1.2.2")])));
    assert_that(&res, not(contains(names(&[("util", "1.0.1")]))));
    assert_that(&res, not(contains(names(&[("util", "1.1.1")]))));
}

#[test]
fn resolving_incompat_versions() {
    let mut reg = registry(vec![
        pkg!(("foo", "1.0.1")),
        pkg!(("foo", "1.0.2")),
        pkg!("bar" => [dep_req("foo", "=1.0.2")]),
    ]);

    assert!(resolve(pkg_id("root"), vec![
        dep_req("foo", "=1.0.1"),
        dep("bar"),
    ], &mut reg).is_err());
}

#[test]
fn resolving_backtrack() {
    let mut reg = registry(vec![
        pkg!(("foo", "1.0.2") => [dep("bar")]),
        pkg!(("foo", "1.0.1") => [dep("baz")]),
        pkg!("bar" => [dep_req("foo", "=2.0.2")]),
        pkg!("baz"),
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep_req("foo", "^1"),
    ], &mut reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.1"),
                                       ("baz", "1.0.0")])));
}

#[test]
fn resolving_allows_multiple_compatible_versions() {
    let mut reg = registry(vec![
        pkg!(("foo", "1.0.0")),
        pkg!(("foo", "2.0.0")),
        pkg!(("foo", "0.1.0")),
        pkg!(("foo", "0.2.0")),

        pkg!("bar" => ["d1", "d2", "d3", "d4"]),
        pkg!("d1" => [dep_req("foo", "1")]),
        pkg!("d2" => [dep_req("foo", "2")]),
        pkg!("d3" => [dep_req("foo", "0.1")]),
        pkg!("d4" => [dep_req("foo", "0.2")]),
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep("bar"),
    ], &mut reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.0"),
                                       ("foo", "2.0.0"),
                                       ("foo", "0.1.0"),
                                       ("foo", "0.2.0"),
                                       ("d1", "1.0.0"),
                                       ("d2", "1.0.0"),
                                       ("d3", "1.0.0"),
                                       ("d4", "1.0.0"),
                                       ("bar", "1.0.0")])));
}

#[test]
fn resolving_with_deep_backtracking() {
    let mut reg = registry(vec![
        pkg!(("foo", "1.0.1") => [dep_req("bar", "1")]),
        pkg!(("foo", "1.0.0") => [dep_req("bar", "2")]),

        pkg!(("bar", "1.0.0") => [dep_req("baz", "=1.0.2"),
                                  dep_req("other", "1")]),
        pkg!(("bar", "2.0.0") => [dep_req("baz", "=1.0.1")]),

        pkg!(("baz", "1.0.2") => [dep_req("other", "2")]),
        pkg!(("baz", "1.0.1")),

        pkg!(("dep_req", "1.0.0")),
        pkg!(("dep_req", "2.0.0")),
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep_req("foo", "1"),
    ], &mut reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.0"),
                                       ("bar", "2.0.0"),
                                       ("baz", "1.0.1")])));
}

#[test]
fn resolving_but_no_exists() {
    let mut reg = registry(vec![
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep_req("foo", "1"),
    ], &mut reg);
    assert!(res.is_err());

    assert_eq!(res.err().unwrap().to_string(), "\
no matching package named `foo` found (required by `root`)
location searched: registry http://example.com/
version required: ^1\
");
}

#[test]
fn resolving_cycle() {
    let mut reg = registry(vec![
        pkg!("foo" => ["foo"]),
    ]);

    let _ = resolve(pkg_id("root"), vec![
        dep_req("foo", "1"),
    ], &mut reg);
}

#[test]
fn hard_equality() {
    extern crate env_logger;
    let mut reg = registry(vec![
        pkg!(("foo", "1.0.1")),
        pkg!(("foo", "1.0.0")),

        pkg!(("bar", "1.0.0") => [dep_req("foo", "1.0.0")]),
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep_req("bar", "1"),
        dep_req("foo", "=1.0.0"),
    ], &mut reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.0"),
                                       ("bar", "1.0.0")])));
}
<commit_msg>binding does not need to be mutable<commit_after>#![deny(warnings)]

extern crate hamcrest;
extern crate cargo;

use std::collections::HashMap;

use hamcrest::{assert_that, equal_to, contains, not};

use cargo::core::source::{SourceId, GitReference};
use cargo::core::dependency::Kind::{self, Development};
use cargo::core::{Dependency, PackageId, Summary, Registry};
use cargo::util::{CargoResult, ToUrl};
use cargo::core::resolver::{self, Method};

fn resolve(pkg: PackageId, deps: Vec<Dependency>, registry: &[Summary])
    -> CargoResult<Vec<PackageId>>
{
    struct MyRegistry<'a>(&'a [Summary]);
    impl<'a> Registry for MyRegistry<'a> {
        fn query(&mut self,
                 dep: &Dependency,
                 f: &mut FnMut(Summary)) -> CargoResult<()> {
            for summary in self.0.iter() {
                if dep.matches(summary) {
                    f(summary.clone());
                }
            }
            Ok(())
        }
    }
    let mut registry = MyRegistry(registry);
    let summary = Summary::new(pkg.clone(), deps, HashMap::new()).unwrap();
    let method = Method::Everything;
    let resolve = resolver::resolve(&[(summary, method)], &[], &mut registry)?;
    let res = resolve.iter().cloned().collect();
    Ok(res)
}

trait ToDep {
    fn to_dep(self) -> Dependency;
}

impl ToDep for &'static str {
    fn to_dep(self) -> Dependency {
        let url = "http://example.com".to_url().unwrap();
        let source_id = SourceId::for_registry(&url);
        Dependency::parse_no_deprecated(self, Some("1.0.0"), &source_id).unwrap()
    }
}

impl ToDep for Dependency {
    fn to_dep(self) -> Dependency {
        self
    }
}

trait ToPkgId {
    fn to_pkgid(&self) -> PackageId;
}

impl ToPkgId for &'static str {
    fn to_pkgid(&self) -> PackageId {
        PackageId::new(*self, "1.0.0", &registry_loc()).unwrap()
    }
}

impl ToPkgId for (&'static str, &'static str) {
    fn to_pkgid(&self) -> PackageId {
        let (name, vers) = *self;
        PackageId::new(name, vers, &registry_loc()).unwrap()
    }
}

macro_rules! pkg {
    ($pkgid:expr => [$($deps:expr),+]) => ({
        let d: Vec<Dependency> = vec![$($deps.to_dep()),+];

        Summary::new($pkgid.to_pkgid(), d, HashMap::new()).unwrap()
    });

    ($pkgid:expr) => (
        Summary::new($pkgid.to_pkgid(), Vec::new(), HashMap::new()).unwrap()
    )
}

fn registry_loc() -> SourceId {
    let remote = "http://example.com".to_url().unwrap();
    SourceId::for_registry(&remote)
}

fn pkg(name: &str) -> Summary {
    Summary::new(pkg_id(name), Vec::new(), HashMap::new()).unwrap()
}

fn pkg_id(name: &str) -> PackageId {
    PackageId::new(name, "1.0.0", &registry_loc()).unwrap()
}

fn pkg_id_loc(name: &str, loc: &str) -> PackageId {
    let remote = loc.to_url();
    let master = GitReference::Branch("master".to_string());
    let source_id = SourceId::for_git(&remote.unwrap(), master);

    PackageId::new(name, "1.0.0", &source_id).unwrap()
}

fn pkg_loc(name: &str, loc: &str) -> Summary {
    Summary::new(pkg_id_loc(name, loc), Vec::new(), HashMap::new()).unwrap()
}

fn dep(name: &str) -> Dependency { dep_req(name, "1.0.0") }
fn dep_req(name: &str, req: &str) -> Dependency {
    let url = "http://example.com".to_url().unwrap();
    let source_id = SourceId::for_registry(&url);
    Dependency::parse_no_deprecated(name, Some(req), &source_id).unwrap()
}

fn dep_loc(name: &str, location: &str) -> Dependency {
    let url = location.to_url().unwrap();
    let master = GitReference::Branch("master".to_string());
    let source_id = SourceId::for_git(&url, master);
    Dependency::parse_no_deprecated(name, Some("1.0.0"), &source_id).unwrap()
}
fn dep_kind(name: &str, kind: Kind) -> Dependency {
    dep(name).set_kind(kind).clone()
}

fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
    pkgs
}

fn names<P: ToPkgId>(names: &[P]) -> Vec<PackageId> {
    names.iter().map(|name| name.to_pkgid()).collect()
}

fn loc_names(names: &[(&'static str, &'static str)]) -> Vec<PackageId> {
    names.iter()
        .map(|&(name, loc)| pkg_id_loc(name, loc)).collect()
}

#[test]
fn test_resolving_empty_dependency_list() {
    let res = resolve(pkg_id("root"), Vec::new(),
                      &mut registry(vec![])).unwrap();

    assert_that(&res, equal_to(&names(&["root"])));
}

#[test]
fn test_resolving_only_package() {
    let reg = registry(vec![pkg("foo")]);
    let res = resolve(pkg_id("root"), vec![dep("foo")], &reg);

    assert_that(&res.unwrap(), contains(names(&["root", "foo"])).exactly());
}

#[test]
fn test_resolving_one_dep() {
    let reg = registry(vec![pkg("foo"), pkg("bar")]);
    let res = resolve(pkg_id("root"), vec![dep("foo")], &reg);

    assert_that(&res.unwrap(), contains(names(&["root", "foo"])).exactly());
}

#[test]
fn test_resolving_multiple_deps() {
    let reg = registry(vec![pkg!("foo"), pkg!("bar"), pkg!("baz")]);
    let res = resolve(pkg_id("root"), vec![dep("foo"), dep("baz")],
                      &reg).unwrap();

    assert_that(&res, contains(names(&["root", "foo", "baz"])).exactly());
}

#[test]
fn test_resolving_transitive_deps() {
    let reg = registry(vec![pkg!("foo"), pkg!("bar" => ["foo"])]);
    let res = resolve(pkg_id("root"), vec![dep("bar")], &reg).unwrap();

    assert_that(&res, contains(names(&["root", "foo", "bar"])));
}

#[test]
fn test_resolving_common_transitive_deps() {
    let reg = registry(vec![pkg!("foo" => ["bar"]), pkg!("bar")]);
    let res = resolve(pkg_id("root"), vec![dep("foo"), dep("bar")],
                      &reg).unwrap();

    assert_that(&res, contains(names(&["root", "foo", "bar"])));
}

#[test]
fn test_resolving_with_same_name() {
    let list = vec![pkg_loc("foo", "http://first.example.com"),
                    pkg_loc("bar", "http://second.example.com")];

    let reg = registry(list);
    let res = resolve(pkg_id("root"),
                      vec![dep_loc("foo", "http://first.example.com"),
                           dep_loc("bar", "http://second.example.com")],
                      &reg);

    let mut names = loc_names(&[("foo", "http://first.example.com"),
                                ("bar", "http://second.example.com")]);

    names.push(pkg_id("root"));

    assert_that(&res.unwrap(), contains(names).exactly());
}

#[test]
fn test_resolving_with_dev_deps() {
    let reg = registry(vec![
        pkg!("foo" => ["bar", dep_kind("baz", Development)]),
        pkg!("baz" => ["bat", dep_kind("bam", Development)]),
        pkg!("bar"),
        pkg!("bat")
    ]);

    let res = resolve(pkg_id("root"),
                      vec![dep("foo"), dep_kind("baz", Development)],
                      &reg).unwrap();

    assert_that(&res, contains(names(&["root", "foo", "bar", "baz"])));
}

#[test]
fn resolving_with_many_versions() {
    let reg = registry(vec![
        pkg!(("foo", "1.0.1")),
        pkg!(("foo", "1.0.2")),
    ]);

    let res = resolve(pkg_id("root"), vec![dep("foo")], &reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.2")])));
}

#[test]
fn resolving_with_specific_version() {
    let reg = registry(vec![
        pkg!(("foo", "1.0.1")),
        pkg!(("foo", "1.0.2")),
    ]);

    let res = resolve(pkg_id("root"), vec![dep_req("foo", "=1.0.1")],
                      &reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.1")])));
}

#[test]
fn test_resolving_maximum_version_with_transitive_deps() {
    let reg = registry(vec![
        pkg!(("util", "1.2.2")),
        pkg!(("util", "1.0.0")),
        pkg!(("util", "1.1.1")),
        pkg!("foo" => [dep_req("util", "1.0.0")]),
        pkg!("bar" => [dep_req("util", ">=1.0.1")]),
    ]);

    let res = resolve(pkg_id("root"), vec![dep_req("foo", "1.0.0"), dep_req("bar", "1.0.0")],
                      &reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.0"),
                                       ("bar", "1.0.0"),
                                       ("util", "1.2.2")])));
    assert_that(&res, not(contains(names(&[("util", "1.0.1")]))));
    assert_that(&res, not(contains(names(&[("util", "1.1.1")]))));
}

#[test]
fn resolving_incompat_versions() {
    let reg = registry(vec![
        pkg!(("foo", "1.0.1")),
        pkg!(("foo", "1.0.2")),
        pkg!("bar" => [dep_req("foo", "=1.0.2")]),
    ]);

    assert!(resolve(pkg_id("root"), vec![
        dep_req("foo", "=1.0.1"),
        dep("bar"),
    ], &reg).is_err());
}

#[test]
fn resolving_backtrack() {
    let reg = registry(vec![
        pkg!(("foo", "1.0.2") => [dep("bar")]),
        pkg!(("foo", "1.0.1") => [dep("baz")]),
        pkg!("bar" => [dep_req("foo", "=2.0.2")]),
        pkg!("baz"),
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep_req("foo", "^1"),
    ], &reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.1"),
                                       ("baz", "1.0.0")])));
}

#[test]
fn resolving_allows_multiple_compatible_versions() {
    let reg = registry(vec![
        pkg!(("foo", "1.0.0")),
        pkg!(("foo", "2.0.0")),
        pkg!(("foo", "0.1.0")),
        pkg!(("foo", "0.2.0")),

        pkg!("bar" => ["d1", "d2", "d3", "d4"]),
        pkg!("d1" => [dep_req("foo", "1")]),
        pkg!("d2" => [dep_req("foo", "2")]),
        pkg!("d3" => [dep_req("foo", "0.1")]),
        pkg!("d4" => [dep_req("foo", "0.2")]),
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep("bar"),
    ], &reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.0"),
                                       ("foo", "2.0.0"),
                                       ("foo", "0.1.0"),
                                       ("foo", "0.2.0"),
                                       ("d1", "1.0.0"),
                                       ("d2", "1.0.0"),
                                       ("d3", "1.0.0"),
                                       ("d4", "1.0.0"),
                                       ("bar", "1.0.0")])));
}

#[test]
fn resolving_with_deep_backtracking() {
    let reg = registry(vec![
        pkg!(("foo", "1.0.1") => [dep_req("bar", "1")]),
        pkg!(("foo", "1.0.0") => [dep_req("bar", "2")]),

        pkg!(("bar", "1.0.0") => [dep_req("baz", "=1.0.2"),
                                  dep_req("other", "1")]),
        pkg!(("bar", "2.0.0") => [dep_req("baz", "=1.0.1")]),

        pkg!(("baz", "1.0.2") => [dep_req("other", "2")]),
        pkg!(("baz", "1.0.1")),

        pkg!(("dep_req", "1.0.0")),
        pkg!(("dep_req", "2.0.0")),
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep_req("foo", "1"),
    ], &reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.0"),
                                       ("bar", "2.0.0"),
                                       ("baz", "1.0.1")])));
}

#[test]
fn resolving_but_no_exists() {
    let reg = registry(vec![
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep_req("foo", "1"),
    ], &reg);
    assert!(res.is_err());

    assert_eq!(res.err().unwrap().to_string(), "\
no matching package named `foo` found (required by `root`)
location searched: registry http://example.com/
version required: ^1\
");
}

#[test]
fn resolving_cycle() {
    let reg = registry(vec![
        pkg!("foo" => ["foo"]),
    ]);

    let _ = resolve(pkg_id("root"), vec![
        dep_req("foo", "1"),
    ], &reg);
}

#[test]
fn hard_equality() {
    extern crate env_logger;
    let reg = registry(vec![
        pkg!(("foo", "1.0.1")),
        pkg!(("foo", "1.0.0")),

        pkg!(("bar", "1.0.0") => [dep_req("foo", "1.0.0")]),
    ]);

    let res = resolve(pkg_id("root"), vec![
        dep_req("bar", "1"),
        dep_req("foo", "=1.0.0"),
    ], &reg).unwrap();

    assert_that(&res, contains(names(&[("root", "1.0.0"),
                                       ("foo", "1.0.0"),
                                       ("bar", "1.0.0")])));
}
<|endoftext|>


<commit_before><commit_msg>Don't skip over the first Tera error.<commit_after><|endoftext|>


<commit_before><commit_msg>Rollup merge of #66786 - jyn514:const-if-match-tests, r=Centril<commit_after>// check-pass

#![feature(const_if_match)]

enum E {
    A,
    B,
    C
}

const fn f(e: E) -> usize {
    match e {
        _ => 0
    }
}

fn main() {
    const X: usize = f(E::C);
    assert_eq!(X, 0);
    assert_eq!(f(E::A), 0);
}
<|endoftext|>


<commit_before><commit_msg>queue replaces distinct as the hash-free demo vertex<commit_after>use std::collections::HashMap;
use std::hash::Hash;

use communication::*;
use communication::pact::Pipeline;

use example_shared::*;
use example_shared::operators::unary::UnaryNotifyExt;

use columnar::Columnar;
use drain::DrainExt;

pub trait QueueExt {
    fn queue(&self) -> Self;
}

impl<G: GraphBuilder, D: Data+Columnar> QueueExt for Stream<G, D>
where G::Timestamp: Hash {

    fn queue(&self) -> Stream<G, D> {
        let mut elements = HashMap::new();
        self.unary_notify(Pipeline, format!("Queue"), vec![], move |input, output, notificator| {
            while let Some((time, data)) = input.pull() {
                let set = elements.entry(time).or_insert(Vec::new());
                for datum in data.drain_temp() { set.push(datum); }

                notificator.notify_at(&time);
            }

            while let Some((time, _count)) = notificator.next() {
                if let Some(mut data) = elements.remove(&time) {
                    output.give_at(&time, data.drain_temp());
                }
            }
        })
    }
}
<|endoftext|>


<commit_before><commit_msg>use gen_weighted_bool<commit_after><|endoftext|>


<commit_before>use redox::Box;
use redox::fs::file::File;
use redox::io::{Read, Write, Seek, SeekFrom};
use redox::mem;
use redox::net::*;
use redox::ptr;
use redox::rand;
use redox::slice;
use redox::{str, String, ToString};
use redox::to_num::*;
use redox::Vec;

/// Ethernet resource
pub struct Resource {
    /// The network
    network: Box<Resource>,
    /// The data
    data: Vec<u8>,
    /// The MAC addresss
    peer_addr: MACAddr,
    /// The ethernet type
    ethertype: u16,
}

impl Resource {
    fn dup(&self) -> Option<Box<Self>> {
        match self.network.dup() {
            Some(network) => Some(box Resource {
                network: network,
                data: self.data.clone(),
                peer_addr: self.peer_addr,
                ethertype: self.ethertype,
            }),
            None => None
        }
    }

    pub fn path(&self, buf: &mut [u8]) -> Option<usize> {
        let path = format!("ethernet://{}/{}", self.peer_addr.to_string(), String::from_num_radix(self.ethertype as usize, 16));

        let mut i = 0;
        for b in path.bytes() {
            if i < buf.len() {
                buf[i] = b;
                i += 1;
            } else {
                break;
            }
        }

        Some(i)
    }

    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        /*
        if self.data.len() > 0 {
            let mut bytes: Vec<u8> = Vec::new();
            swap(&mut self.data, &mut bytes);
            vec.push_all(&bytes);
            return Some(bytes.len());
        }

        loop {
            let mut bytes: Vec<u8> = Vec::new();
            match self.network.read_to_end(&mut bytes) {
                Some(_) => {
                    if let Some(frame) = EthernetII::from_bytes(bytes) {
                        if frame.header.ethertype.get() == self.ethertype &&
                           (unsafe { frame.header.dst.equals(MAC_ADDR) } ||
                            frame.header.dst.equals(BROADCAST_MAC_ADDR)) &&
                           (frame.header.src.equals(self.peer_addr) ||
                            self.peer_addr.equals(BROADCAST_MAC_ADDR)) {
                            vec.push_all(&frame.data);
                            return Some(frame.data.len());
                        }
                    }
                }
                None => return None,
            }
        }
        */
        None
    }

    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let data = Vec::from(buf);

        /*
        match self.network.write(EthernetII {
            header: EthernetIIHeader {
                src: unsafe { MAC_ADDR },
                dst: self.peer_addr,
                ethertype: n16::new(self.ethertype),
            },
            data: data,
        }.to_bytes().as_slice()) {
            Some(_) => return Some(buf.len()),
            None => return None,
        }
        */
        None
    }

    fn seek(&mut self, pos: SeekFrom) -> Option<usize> {
        None
    }

    fn sync(&mut self) -> bool {
        self.network.sync()
    }
}

pub struct Scheme;

impl Scheme {
    fn new() -> Box<Self> {
        box Scheme
    }

    fn open(&mut self, url: &str) -> Option<Box<Resource>> {
        //Split scheme from the rest of the URL
        let (scheme, mut not_scheme) = url.split_at(url.find(':').unwrap_or(url.len()));

        //Remove the starting two slashes
        if not_scheme.starts_with("//") {
            not_scheme = &not_scheme[2..not_scheme.len() - 2];
        }

        //Check host and port vs path
        if not_scheme.starts_with("/") {
            if let Some(mut network) = File::open("network://") {
                if url.path().len() > 0 {
                    let ethertype = url.path().to_num_radix(16) as u16;

                    if url.host().len() > 0 {
                        return Some(box Resource {
                            network: network,
                            data: Vec::new(),
                            peer_addr: MACAddr::from_string(&url.host()),
                            ethertype: ethertype,
                        });
                    } else {
                        loop {
                            let mut bytes: Vec<u8> = Vec::new();
                            match network.read_to_end(&mut bytes) {
                                Some(_) => {
                                    if let Some(frame) = EthernetII::from_bytes(bytes) {
                                        if frame.header.ethertype.get() == ethertype &&
                                           (unsafe { frame.header.dst.equals(MAC_ADDR) } ||
                                            frame.header.dst.equals(BROADCAST_MAC_ADDR)) {
                                            return Some(box Resource {
                                                network: network,
                                                data: frame.data,
                                                peer_addr: frame.header.src,
                                                ethertype: ethertype,
                                            });
                                        }
                                    }
                                }
                                None => break,
                            }
                        }
                    }
                } else {
                    /*
                    debug::d("Ethernet: No ethertype provided\n");
                    */
                }
            }
        }

        None
    }
}
<commit_msg>Forgot to make the userspace ethernet scheme have pub methods in `Resource` and `Scheme`<commit_after>use redox::Box;
use redox::fs::file::File;
use redox::io::{Read, Write, Seek, SeekFrom};
use redox::mem;
use redox::net::*;
use redox::ptr;
use redox::rand;
use redox::slice;
use redox::{str, String, ToString};
use redox::to_num::*;
use redox::Vec;

/// Ethernet resource
pub struct Resource {
    /// The network
    network: Box<Resource>,
    /// The data
    data: Vec<u8>,
    /// The MAC addresss
    peer_addr: MACAddr,
    /// The ethernet type
    ethertype: u16,
}

impl Resource {
    pub fn dup(&self) -> Option<Box<Self>> {
        match self.network.dup() {
            Some(network) => Some(box Resource {
                network: network,
                data: self.data.clone(),
                peer_addr: self.peer_addr,
                ethertype: self.ethertype,
            }),
            None => None
        }
    }

    pub fn path(&self, buf: &mut [u8]) -> Option<usize> {
        let path = format!("ethernet://{}/{}", self.peer_addr.to_string(), String::from_num_radix(self.ethertype as usize, 16));

        let mut i = 0;
        for b in path.bytes() {
            if i < buf.len() {
                buf[i] = b;
                i += 1;
            } else {
                break;
            }
        }

        Some(i)
    }

    pub fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        /*
        if self.data.len() > 0 {
            let mut bytes: Vec<u8> = Vec::new();
            swap(&mut self.data, &mut bytes);
            vec.push_all(&bytes);
            return Some(bytes.len());
        }

        loop {
            let mut bytes: Vec<u8> = Vec::new();
            match self.network.read_to_end(&mut bytes) {
                Some(_) => {
                    if let Some(frame) = EthernetII::from_bytes(bytes) {
                        if frame.header.ethertype.get() == self.ethertype &&
                           (unsafe { frame.header.dst.equals(MAC_ADDR) } ||
                            frame.header.dst.equals(BROADCAST_MAC_ADDR)) &&
                           (frame.header.src.equals(self.peer_addr) ||
                            self.peer_addr.equals(BROADCAST_MAC_ADDR)) {
                            vec.push_all(&frame.data);
                            return Some(frame.data.len());
                        }
                    }
                }
                None => return None,
            }
        }
        */
        None
    }

    pub fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let data = Vec::from(buf);

        /*
        match self.network.write(EthernetII {
            header: EthernetIIHeader {
                src: unsafe { MAC_ADDR },
                dst: self.peer_addr,
                ethertype: n16::new(self.ethertype),
            },
            data: data,
        }.to_bytes().as_slice()) {
            Some(_) => return Some(buf.len()),
            None => return None,
        }
        */
        None
    }

    pub fn seek(&mut self, pos: SeekFrom) -> Option<usize> {
        None
    }

    pub fn sync(&mut self) -> bool {
        self.network.sync()
    }
}

pub struct Scheme;

impl Scheme {
    pub fn new() -> Box<Self> {
        box Scheme
    }

    pub fn open(&mut self, url: &str) -> Option<Box<Resource>> {
        //Split scheme from the rest of the URL
        let (scheme, mut not_scheme) = url.split_at(url.find(':').unwrap_or(url.len()));

        //Remove the starting two slashes
        if not_scheme.starts_with("//") {
            not_scheme = &not_scheme[2..not_scheme.len() - 2];
        }

        //Check host and port vs path
        if not_scheme.starts_with("/") {
            if let Some(mut network) = File::open("network://") {
                if url.path().len() > 0 {
                    let ethertype = url.path().to_num_radix(16) as u16;

                    if url.host().len() > 0 {
                        return Some(box Resource {
                            network: network,
                            data: Vec::new(),
                            peer_addr: MACAddr::from_string(&url.host()),
                            ethertype: ethertype,
                        });
                    } else {
                        loop {
                            let mut bytes: Vec<u8> = Vec::new();
                            match network.read_to_end(&mut bytes) {
                                Some(_) => {
                                    if let Some(frame) = EthernetII::from_bytes(bytes) {
                                        if frame.header.ethertype.get() == ethertype &&
                                           (unsafe { frame.header.dst.equals(MAC_ADDR) } ||
                                            frame.header.dst.equals(BROADCAST_MAC_ADDR)) {
                                            return Some(box Resource {
                                                network: network,
                                                data: frame.data,
                                                peer_addr: frame.header.src,
                                                ethertype: ethertype,
                                            });
                                        }
                                    }
                                }
                                None => break,
                            }
                        }
                    }
                } else {
                    /*
                    debug::d("Ethernet: No ethertype provided\n");
                    */
                }
            }
        }

        None
    }
}
<|endoftext|>