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

// Characters and their corresponding confusables were collected from
// http://www.unicode.org/Public/security/revision-06/confusables.txt

use codemap::mk_sp as make_span;
use errors::DiagnosticBuilder;
use super::StringReader;

const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
    ('ߺ', "Nko Lajanyalan", '_'),
    ('﹍', "Dashed Low Line", '_'),
    ('﹎', "Centreline Low Line", '_'),
    ('﹏', "Wavy Low Line", '_'),
    ('‐', "Hyphen", '-'),
    ('‑', "Non-Breaking Hyphen", '-'),
    ('‒', "Figure Dash", '-'),
    ('–', "En Dash", '-'),
    ('﹘', "Small Em Dash", '-'),
    ('⁃', "Hyphen Bullet", '-'),
    ('˗', "Modifier Letter Minus Sign", '-'),
    ('−', "Minus Sign", '-'),
    ('٫', "Arabic Decimal Separator", ','),
    ('‚', "Single Low-9 Quotation Mark", ','),
    ('ꓹ', "Lisu Letter Tone Na Po", ','),
    (';', "Greek Question Mark", ';'),
    ('ः', "Devanagari Sign Visarga", ':'),
    ('ઃ', "Gujarati Sign Visarga", ':'),
    ('：', "Fullwidth Colon", ':'),
    ('։', "Armenian Full Stop", ':'),
    ('܃', "Syriac Supralinear Colon", ':'),
    ('܄', "Syriac Sublinear Colon", ':'),
    ('︰', "Presentation Form For Vertical Two Dot Leader", ':'),
    ('᠃', "Mongolian Full Stop", ':'),
    ('᠉', "Mongolian Manchu Full Stop", ':'),
    ('⁚', "Two Dot Punctuation", ':'),
    ('׃', "Hebrew Punctuation Sof Pasuq", ':'),
    ('˸', "Modifier Letter Raised Colon", ':'),
    ('꞉', "Modifier Letter Colon", ':'),
    ('∶', "Ratio", ':'),
    ('ː', "Modifier Letter Triangular Colon", ':'),
    ('ꓽ', "Lisu Letter Tone Mya Jeu", ':'),
    ('！', "Fullwidth Exclamation Mark", '!'),
    ('ǃ', "Latin Letter Retroflex Click", '!'),
    ('ʔ', "Latin Letter Glottal Stop", '?'),
    ('ॽ', "Devanagari Letter Glottal Stop", '?'),
    ('Ꭾ', "Cherokee Letter He", '?'),
    ('𝅭', "Musical Symbol Combining Augmentation Dot", '.'),
    ('․', "One Dot Leader", '.'),
    ('۔', "Arabic Full Stop", '.'),
    ('܁', "Syriac Supralinear Full Stop", '.'),
    ('܂', "Syriac Sublinear Full Stop", '.'),
    ('꘎', "Vai Full Stop", '.'),
    ('𐩐', "Kharoshthi Punctuation Dot", '.'),
    ('٠', "Arabic-Indic Digit Zero", '.'),
    ('۰', "Extended Arabic-Indic Digit Zero", '.'),
    ('ꓸ', "Lisu Letter Tone Mya Ti", '.'),
    ('՝', "Armenian Comma", '\''),
    ('＇', "Fullwidth Apostrophe", '\''),
    ('‘', "Left Single Quotation Mark", '\''),
    ('’', "Right Single Quotation Mark", '\''),
    ('‛', "Single High-Reversed-9 Quotation Mark", '\''),
    ('′', "Prime", '\''),
    ('‵', "Reversed Prime", '\''),
    ('՚', "Armenian Apostrophe", '\''),
    ('׳', "Hebrew Punctuation Geresh", '\''),
    ('`', "Greek Varia", '\''),
    ('｀', "Fullwidth Grave Accent", '\''),
    ('΄', "Greek Tonos", '\''),
    ('´', "Greek Oxia", '\''),
    ('᾽', "Greek Koronis", '\''),
    ('᾿', "Greek Psili", '\''),
    ('῾', "Greek Dasia", '\''),
    ('ʹ', "Modifier Letter Prime", '\''),
    ('ʹ', "Greek Numeral Sign", '\''),
    ('ˊ', "Modifier Letter Acute Accent", '\''),
    ('ˋ', "Modifier Letter Grave Accent", '\''),
    ('˴', "Modifier Letter Middle Grave Accent", '\''),
    ('ʻ', "Modifier Letter Turned Comma", '\''),
    ('ʽ', "Modifier Letter Reversed Comma", '\''),
    ('ʼ', "Modifier Letter Apostrophe", '\''),
    ('ʾ', "Modifier Letter Right Half Ring", '\''),
    ('ꞌ', "Latin Small Letter Saltillo", '\''),
    ('י', "Hebrew Letter Yod", '\''),
    ('ߴ', "Nko High Tone Apostrophe", '\''),
    ('ߵ', "Nko Low Tone Apostrophe", '\''),
    ('＂', "Fullwidth Quotation Mark", '"'),
    ('“', "Left Double Quotation Mark", '"'),
    ('”', "Right Double Quotation Mark", '"'),
    ('‟', "Double High-Reversed-9 Quotation Mark", '"'),
    ('″', "Double Prime", '"'),
    ('‶', "Reversed Double Prime", '"'),
    ('〃', "Ditto Mark", '"'),
    ('״', "Hebrew Punctuation Gershayim", '"'),
    ('˝', "Double Acute Accent", '"'),
    ('ʺ', "Modifier Letter Double Prime", '"'),
    ('˶', "Modifier Letter Middle Double Acute Accent", '"'),
    ('˵', "Modifier Letter Middle Double Grave Accent", '"'),
    ('ˮ', "Modifier Letter Double Apostrophe", '"'),
    ('ײ', "Hebrew Ligature Yiddish Double Yod", '"'),
    ('❞', "Heavy Double Comma Quotation Mark Ornament", '"'),
    ('❝', "Heavy Double Turned Comma Quotation Mark Ornament", '"'),
    ('［', "Fullwidth Left Square Bracket", '('),
    ('❨', "Medium Left Parenthesis Ornament", '('),
    ('❲', "Light Left Tortoise Shell Bracket Ornament", '('),
    ('〔', "Left Tortoise Shell Bracket", '('),
    ('﴾', "Ornate Left Parenthesis", '('),
    ('］', "Fullwidth Right Square Bracket", ')'),
    ('❩', "Medium Right Parenthesis Ornament", ')'),
    ('❳', "Light Right Tortoise Shell Bracket Ornament", ')'),
    ('〕', "Right Tortoise Shell Bracket", ')'),
    ('﴿', "Ornate Right Parenthesis", ')'),
    ('❴', "Medium Left Curly Bracket Ornament", '{'),
    ('❵', "Medium Right Curly Bracket Ornament", '}'),
    ('⁎', "Low Asterisk", '*'),
    ('٭', "Arabic Five Pointed Star", '*'),
    ('∗', "Asterisk Operator", '*'),
    ('᜵', "Philippine Single Punctuation", '/'),
    ('⁁', "Caret Insertion Point", '/'),
    ('∕', "Division Slash", '/'),
    ('⁄', "Fraction Slash", '/'),
    ('╱', "Box Drawings Light Diagonal Upper Right To Lower Left", '/'),
    ('⟋', "Mathematical Rising Diagonal", '/'),
    ('⧸', "Big Solidus", '/'),
    ('㇓', "Cjk Stroke Sp", '/'),
    ('〳', "Vertical Kana Repeat Mark Upper Half", '/'),
    ('丿', "Cjk Unified Ideograph-4E3F", '/'),
    ('⼃', "Kangxi Radical Slash", '/'),
    ('＼', "Fullwidth Reverse Solidus", '\\'),
    ('﹨', "Small Reverse Solidus", '\\'),
    ('∖', "Set Minus", '\\'),
    ('⟍', "Mathematical Falling Diagonal", '\\'),
    ('⧵', "Reverse Solidus Operator", '\\'),
    ('⧹', "Big Reverse Solidus", '\\'),
    ('㇔', "Cjk Stroke D", '\\'),
    ('丶', "Cjk Unified Ideograph-4E36", '\\'),
    ('⼂', "Kangxi Radical Dot", '\\'),
    ('ꝸ', "Latin Small Letter Um", '&'),
    ('﬩', "Hebrew Letter Alternative Plus Sign", '+'),
    ('‹', "Single Left-Pointing Angle Quotation Mark", '<'),
    ('❮', "Heavy Left-Pointing Angle Quotation Mark Ornament", '<'),
    ('˂', "Modifier Letter Left Arrowhead", '<'),
    ('꓿', "Lisu Punctuation Full Stop", '='),
    ('›', "Single Right-Pointing Angle Quotation Mark", '>'),
    ('❯', "Heavy Right-Pointing Angle Quotation Mark Ornament", '>'),
    ('˃', "Modifier Letter Right Arrowhead", '>'),
    ('Ⲻ', "Coptic Capital Letter Dialect-P Ni", '-'),
    ('Ɂ', "Latin Capital Letter Glottal Stop", '?'),
    ('Ⳇ', "Coptic Capital Letter Old Coptic Esh", '/'), ];

const ASCII_ARRAY: &'static [(char, &'static str)] = &[
    ('_', "Underscore"),
    ('-', "Minus/Hyphen"),
    (',', "Comma"),
    (';', "Semicolon"),
    (':', "Colon"),
    ('!', "Exclamation Mark"),
    ('?', "Question Mark"),
    ('.', "Period"),
    ('\'', "Single Quote"),
    ('"', "Quotation Mark"),
    ('(', "Left Parenthesis"),
    (')', "Right Parenthesis"),
    ('{', "Left Curly Brace"),
    ('}', "Right Curly Brace"),
    ('*', "Asterisk"),
    ('/', "Slash"),
    ('\\', "Backslash"),
    ('&', "Ampersand"),
    ('+', "Plus Sign"),
    ('<', "Less-Than Sign"),
    ('=', "Equals Sign"),
    ('>', "Greater-Than Sign"), ];

pub fn check_for_substitution<'a>(reader: &StringReader<'a>,
                                  ch: char,
                                  err: &mut DiagnosticBuilder<'a>) {
    UNICODE_ARRAY
    .iter()
    .find(|&&(c, _, _)| c == ch)
    .map(|&(_, u_name, ascii_char)| {
        let span = make_span(reader.last_pos, reader.pos);
        match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
            Some(&(ascii_char, ascii_name)) => {
                let msg =
                    format!("unicode character '{}' ({}) looks much like '{}' ({}), but it's not",
                            ch, u_name, ascii_char, ascii_name);
                err.span_help(span, &msg);
            },
            None => {
                reader
                .span_diagnostic
                .span_bug_no_panic(span,
                                   &format!("substitution character not found for '{}'", ch));
            }
        }
    });
}
<commit_msg>Auto merge of #33128 - xen0n:more-confusing-unicode-chars, r=nagisa<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Characters and their corresponding confusables were collected from
// http://www.unicode.org/Public/security/revision-06/confusables.txt

use codemap::mk_sp as make_span;
use errors::DiagnosticBuilder;
use super::StringReader;

const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
    (' ', "No-Break Space", ' '),
    (' ', "Ogham Space Mark", ' '),
    (' ', "En Quad", ' '),
    (' ', "Em Quad", ' '),
    (' ', "En Space", ' '),
    (' ', "Em Space", ' '),
    (' ', "Three-Per-Em Space", ' '),
    (' ', "Four-Per-Em Space", ' '),
    (' ', "Six-Per-Em Space", ' '),
    (' ', "Figure Space", ' '),
    (' ', "Punctuation Space", ' '),
    (' ', "Thin Space", ' '),
    (' ', "Hair Space", ' '),
    (' ', "Narrow No-Break Space", ' '),
    (' ', "Medium Mathematical Space", ' '),
    ('　', "Ideographic Space", ' '),
    ('ߺ', "Nko Lajanyalan", '_'),
    ('﹍', "Dashed Low Line", '_'),
    ('﹎', "Centreline Low Line", '_'),
    ('﹏', "Wavy Low Line", '_'),
    ('‐', "Hyphen", '-'),
    ('‑', "Non-Breaking Hyphen", '-'),
    ('‒', "Figure Dash", '-'),
    ('–', "En Dash", '-'),
    ('—', "Em Dash", '-'),
    ('﹘', "Small Em Dash", '-'),
    ('⁃', "Hyphen Bullet", '-'),
    ('˗', "Modifier Letter Minus Sign", '-'),
    ('−', "Minus Sign", '-'),
    ('ー', "Katakana-Hiragana Prolonged Sound Mark", '-'),
    ('٫', "Arabic Decimal Separator", ','),
    ('‚', "Single Low-9 Quotation Mark", ','),
    ('ꓹ', "Lisu Letter Tone Na Po", ','),
    ('，', "Fullwidth Comma", ','),
    (';', "Greek Question Mark", ';'),
    ('；', "Fullwidth Semicolon", ';'),
    ('ः', "Devanagari Sign Visarga", ':'),
    ('ઃ', "Gujarati Sign Visarga", ':'),
    ('：', "Fullwidth Colon", ':'),
    ('։', "Armenian Full Stop", ':'),
    ('܃', "Syriac Supralinear Colon", ':'),
    ('܄', "Syriac Sublinear Colon", ':'),
    ('︰', "Presentation Form For Vertical Two Dot Leader", ':'),
    ('᠃', "Mongolian Full Stop", ':'),
    ('᠉', "Mongolian Manchu Full Stop", ':'),
    ('⁚', "Two Dot Punctuation", ':'),
    ('׃', "Hebrew Punctuation Sof Pasuq", ':'),
    ('˸', "Modifier Letter Raised Colon", ':'),
    ('꞉', "Modifier Letter Colon", ':'),
    ('∶', "Ratio", ':'),
    ('ː', "Modifier Letter Triangular Colon", ':'),
    ('ꓽ', "Lisu Letter Tone Mya Jeu", ':'),
    ('！', "Fullwidth Exclamation Mark", '!'),
    ('ǃ', "Latin Letter Retroflex Click", '!'),
    ('ʔ', "Latin Letter Glottal Stop", '?'),
    ('ॽ', "Devanagari Letter Glottal Stop", '?'),
    ('Ꭾ', "Cherokee Letter He", '?'),
    ('？', "Fullwidth Question Mark", '?'),
    ('𝅭', "Musical Symbol Combining Augmentation Dot", '.'),
    ('․', "One Dot Leader", '.'),
    ('۔', "Arabic Full Stop", '.'),
    ('܁', "Syriac Supralinear Full Stop", '.'),
    ('܂', "Syriac Sublinear Full Stop", '.'),
    ('꘎', "Vai Full Stop", '.'),
    ('𐩐', "Kharoshthi Punctuation Dot", '.'),
    ('·', "Middle Dot", '.'),
    ('٠', "Arabic-Indic Digit Zero", '.'),
    ('۰', "Extended Arabic-Indic Digit Zero", '.'),
    ('ꓸ', "Lisu Letter Tone Mya Ti", '.'),
    ('。', "Ideographic Full Stop", '.'),
    ('・', "Katakana Middle Dot", '.'),
    ('՝', "Armenian Comma", '\''),
    ('＇', "Fullwidth Apostrophe", '\''),
    ('‘', "Left Single Quotation Mark", '\''),
    ('’', "Right Single Quotation Mark", '\''),
    ('‛', "Single High-Reversed-9 Quotation Mark", '\''),
    ('′', "Prime", '\''),
    ('‵', "Reversed Prime", '\''),
    ('՚', "Armenian Apostrophe", '\''),
    ('׳', "Hebrew Punctuation Geresh", '\''),
    ('`', "Greek Varia", '\''),
    ('｀', "Fullwidth Grave Accent", '\''),
    ('΄', "Greek Tonos", '\''),
    ('´', "Greek Oxia", '\''),
    ('᾽', "Greek Koronis", '\''),
    ('᾿', "Greek Psili", '\''),
    ('῾', "Greek Dasia", '\''),
    ('ʹ', "Modifier Letter Prime", '\''),
    ('ʹ', "Greek Numeral Sign", '\''),
    ('ˊ', "Modifier Letter Acute Accent", '\''),
    ('ˋ', "Modifier Letter Grave Accent", '\''),
    ('˴', "Modifier Letter Middle Grave Accent", '\''),
    ('ʻ', "Modifier Letter Turned Comma", '\''),
    ('ʽ', "Modifier Letter Reversed Comma", '\''),
    ('ʼ', "Modifier Letter Apostrophe", '\''),
    ('ʾ', "Modifier Letter Right Half Ring", '\''),
    ('ꞌ', "Latin Small Letter Saltillo", '\''),
    ('י', "Hebrew Letter Yod", '\''),
    ('ߴ', "Nko High Tone Apostrophe", '\''),
    ('ߵ', "Nko Low Tone Apostrophe", '\''),
    ('＂', "Fullwidth Quotation Mark", '"'),
    ('“', "Left Double Quotation Mark", '"'),
    ('”', "Right Double Quotation Mark", '"'),
    ('‟', "Double High-Reversed-9 Quotation Mark", '"'),
    ('″', "Double Prime", '"'),
    ('‶', "Reversed Double Prime", '"'),
    ('〃', "Ditto Mark", '"'),
    ('״', "Hebrew Punctuation Gershayim", '"'),
    ('˝', "Double Acute Accent", '"'),
    ('ʺ', "Modifier Letter Double Prime", '"'),
    ('˶', "Modifier Letter Middle Double Acute Accent", '"'),
    ('˵', "Modifier Letter Middle Double Grave Accent", '"'),
    ('ˮ', "Modifier Letter Double Apostrophe", '"'),
    ('ײ', "Hebrew Ligature Yiddish Double Yod", '"'),
    ('❞', "Heavy Double Comma Quotation Mark Ornament", '"'),
    ('❝', "Heavy Double Turned Comma Quotation Mark Ornament", '"'),
    ('❨', "Medium Left Parenthesis Ornament", '('),
    ('﴾', "Ornate Left Parenthesis", '('),
    ('（', "Fullwidth Left Parenthesis", '('),
    ('❩', "Medium Right Parenthesis Ornament", ')'),
    ('﴿', "Ornate Right Parenthesis", ')'),
    ('）', "Fullwidth Right Parenthesis", ')'),
    ('［', "Fullwidth Left Square Bracket", '['),
    ('❲', "Light Left Tortoise Shell Bracket Ornament", '['),
    ('「', "Left Corner Bracket", '['),
    ('『', "Left White Corner Bracket", '['),
    ('【', "Left Black Lenticular Bracket", '['),
    ('〔', "Left Tortoise Shell Bracket", '['),
    ('〖', "Left White Lenticular Bracket", '['),
    ('〘', "Left White Tortoise Shell Bracket", '['),
    ('〚', "Left White Square Bracket", '['),
    ('］', "Fullwidth Right Square Bracket", ']'),
    ('❳', "Light Right Tortoise Shell Bracket Ornament", ']'),
    ('」', "Right Corner Bracket", ']'),
    ('』', "Right White Corner Bracket", ']'),
    ('】', "Right Black Lenticular Bracket", ']'),
    ('〕', "Right Tortoise Shell Bracket", ']'),
    ('〗', "Right White Lenticular Bracket", ']'),
    ('〙', "Right White Tortoise Shell Bracket", ']'),
    ('〛', "Right White Square Bracket", ']'),
    ('❴', "Medium Left Curly Bracket Ornament", '{'),
    ('❵', "Medium Right Curly Bracket Ornament", '}'),
    ('⁎', "Low Asterisk", '*'),
    ('٭', "Arabic Five Pointed Star", '*'),
    ('∗', "Asterisk Operator", '*'),
    ('᜵', "Philippine Single Punctuation", '/'),
    ('⁁', "Caret Insertion Point", '/'),
    ('∕', "Division Slash", '/'),
    ('⁄', "Fraction Slash", '/'),
    ('╱', "Box Drawings Light Diagonal Upper Right To Lower Left", '/'),
    ('⟋', "Mathematical Rising Diagonal", '/'),
    ('⧸', "Big Solidus", '/'),
    ('㇓', "Cjk Stroke Sp", '/'),
    ('〳', "Vertical Kana Repeat Mark Upper Half", '/'),
    ('丿', "Cjk Unified Ideograph-4E3F", '/'),
    ('⼃', "Kangxi Radical Slash", '/'),
    ('＼', "Fullwidth Reverse Solidus", '\\'),
    ('﹨', "Small Reverse Solidus", '\\'),
    ('∖', "Set Minus", '\\'),
    ('⟍', "Mathematical Falling Diagonal", '\\'),
    ('⧵', "Reverse Solidus Operator", '\\'),
    ('⧹', "Big Reverse Solidus", '\\'),
    ('、', "Ideographic Comma", '\\'),
    ('ヽ', "Katakana Iteration Mark", '\\'),
    ('㇔', "Cjk Stroke D", '\\'),
    ('丶', "Cjk Unified Ideograph-4E36", '\\'),
    ('⼂', "Kangxi Radical Dot", '\\'),
    ('ꝸ', "Latin Small Letter Um", '&'),
    ('﬩', "Hebrew Letter Alternative Plus Sign", '+'),
    ('‹', "Single Left-Pointing Angle Quotation Mark", '<'),
    ('❮', "Heavy Left-Pointing Angle Quotation Mark Ornament", '<'),
    ('˂', "Modifier Letter Left Arrowhead", '<'),
    ('〈', "Left Angle Bracket", '<'),
    ('《', "Left Double Angle Bracket", '<'),
    ('꓿', "Lisu Punctuation Full Stop", '='),
    ('›', "Single Right-Pointing Angle Quotation Mark", '>'),
    ('❯', "Heavy Right-Pointing Angle Quotation Mark Ornament", '>'),
    ('˃', "Modifier Letter Right Arrowhead", '>'),
    ('〉', "Right Angle Bracket", '>'),
    ('》', "Right Double Angle Bracket", '>'),
    ('Ⲻ', "Coptic Capital Letter Dialect-P Ni", '-'),
    ('Ɂ', "Latin Capital Letter Glottal Stop", '?'),
    ('Ⳇ', "Coptic Capital Letter Old Coptic Esh", '/'), ];

const ASCII_ARRAY: &'static [(char, &'static str)] = &[
    (' ', "Space"),
    ('_', "Underscore"),
    ('-', "Minus/Hyphen"),
    (',', "Comma"),
    (';', "Semicolon"),
    (':', "Colon"),
    ('!', "Exclamation Mark"),
    ('?', "Question Mark"),
    ('.', "Period"),
    ('\'', "Single Quote"),
    ('"', "Quotation Mark"),
    ('(', "Left Parenthesis"),
    (')', "Right Parenthesis"),
    ('[', "Left Square Bracket"),
    (']', "Right Square Bracket"),
    ('{', "Left Curly Brace"),
    ('}', "Right Curly Brace"),
    ('*', "Asterisk"),
    ('/', "Slash"),
    ('\\', "Backslash"),
    ('&', "Ampersand"),
    ('+', "Plus Sign"),
    ('<', "Less-Than Sign"),
    ('=', "Equals Sign"),
    ('>', "Greater-Than Sign"), ];

pub fn check_for_substitution<'a>(reader: &StringReader<'a>,
                                  ch: char,
                                  err: &mut DiagnosticBuilder<'a>) {
    UNICODE_ARRAY
    .iter()
    .find(|&&(c, _, _)| c == ch)
    .map(|&(_, u_name, ascii_char)| {
        let span = make_span(reader.last_pos, reader.pos);
        match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
            Some(&(ascii_char, ascii_name)) => {
                let msg =
                    format!("unicode character '{}' ({}) looks much like '{}' ({}), but it's not",
                            ch, u_name, ascii_char, ascii_name);
                err.span_help(span, &msg);
            },
            None => {
                reader
                .span_diagnostic
                .span_bug_no_panic(span,
                                   &format!("substitution character not found for '{}'", ch));
            }
        }
    });
}
<|endoftext|>


<commit_before><commit_msg>fix breakage from https://github.com/rust-lang/rust/pull/19891<commit_after><|endoftext|>


<commit_before><commit_msg>rename count_map.rs<commit_after>//! A collection of updates of the form `(T, i64)`.

/// A collection of updates of the form `(T, i64)`.
///
/// A `ChangeBatch` accumulates updates of the form `(T, i64)`, where it is capable of consolidating
/// the representation and removing elements whose `i64` field accumulates to zero.
///
/// The implementation is designed to be as lazy as possible, simply appending to a list of updates
/// until they are required. This means that several seemingly simple operations may be expensive, in
/// that they may provoke a compaction. I've tried to prevent exposing methods that allow surprisingly
/// expensive operations; all operations should take an amortized constant or logarithmic time.
#[derive(Clone, Debug)]
pub struct ChangeBatch<T> {
    // A list of updates to which we append.
    updates: Vec<(T, i64)>,
    // The length of the prefix of `self.updates` known to be compact.
    clean: usize,
}

impl<T:Ord> ChangeBatch<T> {

    /// Allocates a new empty `ChangeBatch`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new();
    /// assert!(batch.is_empty());
    ///```
    pub fn new() -> ChangeBatch<T> {
        ChangeBatch {
            updates: Vec::new(),
            clean: 0
        }
    }

    /// Allocates a new `ChangeBatch` with a single entry.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// assert!(!batch.is_empty());
    ///```
    pub fn new_from(key: T, val: i64) -> ChangeBatch<T> {
        let mut result = ChangeBatch::new();
        result.update(key, val);
        result
    }

    /// Adds a new update, for `item` with `value`.
    ///
    /// This could be optimized to perform compaction when the number of "dirty" elements exceeds
    /// half the length of the list, which would keep the total footprint within reasonable bounds
    /// even under an arbitrary number of updates. This has a cost, and it isn't clear whether it
    /// is worth paying without some experimentation.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new();
    /// batch.update(17, 1);
    /// assert!(!batch.is_empty());
    ///```
    pub fn update(&mut self, item: T, value: i64) {
        self.updates.push((item, value));
    }

    /// Performs a sequence of updates described by `iterator`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// batch.extend(vec![(17, -1)].into_iter());
    /// assert!(batch.is_empty());
    ///```
    pub fn extend<I: Iterator<Item=(T, i64)>>(&mut self, iterator: I) {
        for (key, val) in iterator {
            self.update(key, val);
        }
    }

    /// Extracts the `Vec<(T, i64)>` from the map, consuming it.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let batch = ChangeBatch::<usize>::new_from(17, 1);
    /// assert_eq!(batch.into_inner(), vec![(17, 1)]);
    ///```
    pub fn into_inner(mut self) -> Vec<(T, i64)> {
        self.compact();
        self.updates
    }

    /// Iterates over the contents of the map.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// {   // scope allows borrow of `batch` to drop.
    ///     let mut iter = batch.iter();
    ///     assert_eq!(iter.next(), Some(&(17, 1)));
    ///     assert_eq!(iter.next(), None);
    /// }
    /// assert!(!batch.is_empty());
    ///```
    pub fn iter(&mut self) -> ::std::slice::Iter<(T, i64)> {
        self.compact();
        self.updates.iter()
    }

    /// Drains the set of updates.
    ///
    /// This operation first compacts the set of updates so that the drained results
    /// have at most one occurence of each item.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// {   // scope allows borrow of `batch` to drop.
    ///     let mut iter = batch.drain();
    ///     assert_eq!(iter.next(), Some((17, 1)));
    ///     assert_eq!(iter.next(), None);
    /// }
    /// assert!(batch.is_empty());
    ///```
    pub fn drain(&mut self) -> ::std::vec::Drain<(T, i64)> {
        self.compact();
        self.clean = 0;
        self.updates.drain(..)
    }

    /// Clears the map.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// batch.clear();
    /// assert!(batch.is_empty());
    ///```
    pub fn clear(&mut self) {
        self.updates.clear();
        self.clean = 0;
    }

    /// True iff all keys have value zero.
    ///
    /// This method requires mutable access to `self` because it may need to compact the representation
    /// to determine if the batch of updates is indeed empty. We could also implement a weaker form of
    /// `is_empty` which just checks the length of `self.updates`, and which could confirm the absence of
    /// any updates, but could report false negatives if there are updates which would cancel.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// batch.update(17, -1);
    /// assert!(batch.is_empty());
    ///```
    pub fn is_empty(&mut self) -> bool {
        if self.clean > self.updates.len() / 2 {
            false
        }
        else {
            self.compact();
            self.updates.is_empty()
        }
    }

    /// Drains `self` into `other`.
    ///
    /// This method has similar a effect to calling `other.extend(self.drain())`, but has the
    /// opportunity to optimize this to a `::std::mem::swap(self, other)` when `other` is empty.
    /// As many uses of this method are to propagate updates, this optimization can be quite
    /// handy.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch1 = ChangeBatch::<usize>::new_from(17, 1);
    /// let mut batch2 = ChangeBatch::new();
    /// batch1.drain_into(&mut batch2);
    /// assert!(batch1.is_empty());
    /// assert!(!batch2.is_empty());
    ///```
    pub fn drain_into(&mut self, other: &mut ChangeBatch<T>) where T: Clone {
        if other.updates.len() == 0 {
            ::std::mem::swap(self, other);
        }
        else {
            while let Some((ref key, val)) = self.updates.pop() {
                other.update(key.clone(), val);
            }
        }
    }

    /// Compact the internal representation.
    ///
    /// This method sort `self.updates` and consolidates elements with equal item, discarding
    /// any whose accumulation is zero. It is optimized to only do this if the number of dirty
    /// elements is non-zero.
    fn compact(&mut self) {
        if self.clean < self.updates.len() && self.updates.len() > 0 {
            self.updates.sort_by(|x,y| x.0.cmp(&y.0));
            for i in 0 .. self.updates.len() - 1 {
                if self.updates[i].0 == self.updates[i+1].0 {
                    self.updates[i+1].1 += self.updates[i].1;
                    self.updates[i].1 = 0;
                }
            }
            self.updates.retain(|x| x.1 != 0);
        }
        self.clean = self.updates.len();
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Various helper macros.

mod pso;
mod structure;

#[macro_export]
macro_rules! gfx_format {
    ($name:ident : $surface:ident = $container:ident<$channel:ident>) => {
        impl $crate::format::Formatted for $name {
            type Surface = $crate::format::$surface;
            type Channel = $crate::format::$channel;
            type View = $crate::format::$container<
                <$crate::format::$channel as $crate::format::ChannelTyped>::ShaderType
                >;
        }
    }
}

/// Defines vertex, constant and pipeline formats in one block
#[macro_export]
macro_rules! gfx_defines {
    (vertex $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_vertex_struct!($name {$($field:$ty = $e,)+});
    };

    (constant $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_constant_struct!($name {$($field:$ty = $e,)+});
    };

    (pipeline $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_pipeline!($name {$($field:$ty = $e,)+});
    };

    ($keyword:ident $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    } $($tail:tt)+) => {
        gfx_defines! {
            $keyword $name { $($field : $ty = $e,)+ }
        }
        gfx_defines!($($tail)+);
    }
}
<commit_msg>Make trailing comma optional in gfx_defines! declarations<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Various helper macros.

mod pso;
mod structure;

#[macro_export]
macro_rules! gfx_format {
    ($name:ident : $surface:ident = $container:ident<$channel:ident>) => {
        impl $crate::format::Formatted for $name {
            type Surface = $crate::format::$surface;
            type Channel = $crate::format::$channel;
            type View = $crate::format::$container<
                <$crate::format::$channel as $crate::format::ChannelTyped>::ShaderType
                >;
        }
    }
}

/// Defines vertex, constant and pipeline formats in one block
#[macro_export]
macro_rules! gfx_defines {
    (vertex $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_vertex_struct!($name {$($field:$ty = $e,)+});
    };

    (constant $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_constant_struct!($name {$($field:$ty = $e,)+});
    };

    (pipeline $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_pipeline!($name {$($field:$ty = $e,)+});
    };

    ($keyword:ident $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    } $($tail:tt)+) => {
        gfx_defines! {
            $keyword $name { $($field : $ty = $e,)+ }
        }
        gfx_defines!($($tail)+);
    };

    ($keyword:ident $name:ident {
            $( $field:ident : $ty:ty = $e:expr ),*
    }) => {
        gfx_defines! {
            $keyword $name {
                $($field : $ty = $e ,)*
            }
        }
    };
}
<|endoftext|>


<commit_before><commit_msg>Revert "Fix accidental two blank lines"<commit_after><|endoftext|>


<commit_before><commit_msg>new merging spine<commit_after>//! An append-only collection of update batches.
//!
//! The `Spine` is a general-purpose trace implementation based on collection and merging
//! immutable batches of updates. It is generic with respect to the batch type, and can be
//! instantiated for any implementor of `trace::Batch`.

use std::fmt::Debug;

use ::difference::Monoid;
use lattice::Lattice;
use trace::{Batch, BatchReader, Trace, TraceReader};
// use trace::cursor::cursor_list::CursorList;
use trace::cursor::{Cursor, CursorList};
use trace::Merger;

use ::timely::dataflow::operators::generic::OperatorInfo;

/// An append-only collection of update tuples.
///
/// A spine maintains a small number of immutable collections of update tuples, merging the collections when
/// two have similar sizes. In this way, it allows the addition of more tuples, which may then be merged with
/// other immutable collections.
pub struct Spine<K, V, T: Lattice+Ord, R: Monoid, B: Batch<K, V, T, R>> {
    operator: OperatorInfo,
    logger: Option<::logging::Logger>,
    phantom: ::std::marker::PhantomData<(K, V, R)>,
    advance_frontier: Vec<T>,                   // Times after which the trace must accumulate correctly.
    through_frontier: Vec<T>,                   // Times after which the trace must be able to subset its inputs.
    merging: Vec<Option<MergeState<K,V,T,R,B>>>,// Several possibly shared collections of updates.
    pending: Vec<B>,                       // Batches at times in advance of `frontier`.
    upper: Vec<T>,
    effort: usize,
    activator: Option<timely::scheduling::activate::Activator>,
}

impl<K, V, T, R, B> TraceReader for Spine<K, V, T, R, B>
where
    K: Ord+Clone,           // Clone is required by `batch::advance_*` (in-place could remove).
    V: Ord+Clone,           // Clone is required by `batch::advance_*` (in-place could remove).
    T: Lattice+Ord+Clone+Debug+Default,
    R: Monoid,
    B: Batch<K, V, T, R>+Clone+'static,
{
    type Key = K;
    type Val = V;
    type Time = T;
    type R = R;

    type Batch = B;
    type Cursor = CursorList<K, V, T, R, <B as BatchReader<K, V, T, R>>::Cursor>;

    fn cursor_through(&mut self, upper: &[T]) -> Option<(Self::Cursor, <Self::Cursor as Cursor<K, V, T, R>>::Storage)> {

        // The supplied `upper` should have the property that for each of our
        // batch `lower` and `upper` frontiers, the supplied upper is comparable
        // to the frontier; it should not be incomparable, because the frontiers
        // that we created form a total order. If it is, there is a bug.
        //
        // We should acquire a cursor including all batches whose upper is less
        // or equal to the supplied upper, excluding all batches whose lower is
        // greater or equal to the supplied upper, and if a batch straddles the
        // supplied upper it had better be empty.

        // We shouldn't grab a cursor into a closed trace, right?
        assert!(self.advance_frontier.len() > 0);

        // Check that `upper` is greater or equal to `self.through_frontier`.
        // Otherwise, the cut could be in `self.merging` and it is user error anyhow.
        assert!(upper.iter().all(|t1| self.through_frontier.iter().any(|t2| t2.less_equal(t1))));

        let mut cursors = Vec::new();
        let mut storage = Vec::new();

        for merge_state in self.merging.iter().rev() {
            match *merge_state {
                Some(MergeState::Merging(ref batch1, ref batch2, _, _)) => {
                    if !batch1.is_empty() {
                        cursors.push(batch1.cursor());
                        storage.push(batch1.clone());
                    }
                    if !batch2.is_empty() {
                        cursors.push(batch2.cursor());
                        storage.push(batch2.clone());
                    }
                },
                Some(MergeState::Complete(ref batch)) => {
                    if !batch.is_empty() {
                        cursors.push(batch.cursor());
                        storage.push(batch.clone());
                    }
                },
                None => { }
            }
        }

        for batch in self.pending.iter() {

            if !batch.is_empty() {

                // For a non-empty `batch`, it is a catastrophic error if `upper`
                // requires some-but-not-all of the updates in the batch. We can
                // determine this from `upper` and the lower and upper bounds of
                // the batch itself.
                //
                // TODO: It is not clear if this is the 100% correct logic, due
                // to the possible non-total-orderedness of the frontiers.

                let include_lower = upper.iter().all(|t1| batch.lower().iter().any(|t2| t2.less_equal(t1)));
                let include_upper = upper.iter().all(|t1| batch.upper().iter().any(|t2| t2.less_equal(t1)));

                if include_lower != include_upper && upper != batch.lower() {
                    panic!("`cursor_through`: `upper` straddles batch");
                }

                // include pending batches
                if include_upper {
                    cursors.push(batch.cursor());
                    storage.push(batch.clone());
                }
            }
        }

        Some((CursorList::new(cursors, &storage), storage))
    }
    fn advance_by(&mut self, frontier: &[T]) {
        self.advance_frontier = frontier.to_vec();
        if self.advance_frontier.len() == 0 {
            self.pending.clear();
            self.merging.clear();
        }
    }
    fn advance_frontier(&mut self) -> &[T] { &self.advance_frontier[..] }
    fn distinguish_since(&mut self, frontier: &[T]) {
        self.through_frontier = frontier.to_vec();
        self.consider_merges();
    }
    fn distinguish_frontier(&mut self) -> &[T] { &self.through_frontier[..] }

    fn map_batches<F: FnMut(&Self::Batch)>(&mut self, mut f: F) {
        for batch in self.merging.iter().rev() {
            match *batch {
                Some(MergeState::Merging(ref batch1, ref batch2, _, _)) => { f(batch1); f(batch2); },
                Some(MergeState::Complete(ref batch)) => { f(batch); },
                None => { },
            }
        }
        for batch in self.pending.iter() {
            f(batch);
        }
    }
}

// A trace implementation for any key type that can be borrowed from or converted into `Key`.
// TODO: Almost all this implementation seems to be generic with respect to the trace and batch types.
impl<K, V, T, R, B> Trace for Spine<K, V, T, R, B>
where
    K: Ord+Clone,
    V: Ord+Clone,
    T: Lattice+Ord+Clone+Debug+Default,
    R: Monoid,
    B: Batch<K, V, T, R>+Clone+'static,
{

    fn new(
        info: ::timely::dataflow::operators::generic::OperatorInfo,
        logging: Option<::logging::Logger>,
        activator: Option<timely::scheduling::activate::Activator>,
    ) -> Self {
        Self::with_effort(4, info, logging, activator)
    }

    fn exert(&mut self, batch_size: usize, batch_index: usize) {
        self.work_for(batch_size, batch_index);
    }

    // Ideally, this method acts as insertion of `batch`, even if we are not yet able to begin
    // merging the batch. This means it is a good time to perform amortized work proportional
    // to the size of batch.
    fn insert(&mut self, batch: Self::Batch) {

        self.logger.as_ref().map(|l| l.log(::logging::BatchEvent {
            operator: self.operator.global_id,
            length: batch.len()
        }));

        assert!(batch.lower() != batch.upper());
        assert_eq!(batch.lower(), &self.upper[..]);

        self.upper = batch.upper().to_vec();

        // TODO: Consolidate or discard empty batches.
        self.pending.push(batch);
        self.consider_merges();
    }

    fn close(&mut self) {
        if !self.upper.is_empty() {
            use trace::Builder;
            let builder = B::Builder::new();
            let batch = builder.done(&self.upper[..], &[], &self.upper[..]);
            self.insert(batch);
        }
    }
}

impl<K, V, T, R, B> Spine<K, V, T, R, B>
where
    K: Ord+Clone,
    V: Ord+Clone,
    T: Lattice+Ord+Clone+Debug+Default,
    R: Monoid,
    B: Batch<K, V, T, R>,
{
    /// Allocates a fueled `Spine` with a specified effort multiplier.
    ///
    /// This trace will merge batches progressively, with each inserted batch applying a multiple
    /// of the batch's length in effort to each merge. The `effort` parameter is that multiplier.
    /// This value should be at least one for the merging to happen; a value of zero is not helpful.
    pub fn with_effort(
        mut effort: usize,
        operator: OperatorInfo,
        logger: Option<::logging::Logger>,
        activator: Option<timely::scheduling::activate::Activator>,
    ) -> Self {

        // Zero effort is .. not smart.
        if effort == 0 { effort = 1; }

        Spine {
            operator,
            logger,
            phantom: ::std::marker::PhantomData,
            advance_frontier: vec![<T as Lattice>::minimum()],
            through_frontier: vec![<T as Lattice>::minimum()],
            merging: Vec::new(),
            pending: Vec::new(),
            upper: vec![Default::default()],
            effort,
            activator,
        }
    }

    // Migrate data from `self.pending` into `self.merging`.
    #[inline(never)]
    fn consider_merges(&mut self) {

        while self.pending.len() > 0 &&
              self.through_frontier.iter().all(|t1| self.pending[0].upper().iter().any(|t2| t2.less_equal(t1)))
        {
            // this could be a VecDeque, if we ever notice this.
            let batch = self.pending.remove(0);

            self.introduce_batch(batch, batch.len().next_power_of_two());

            // Having performed all of our work, if more than one batch remains reschedule ourself.
            if self.merging.len() > 2 && self.merging[..self.merging.len()-1].iter().any(|b| b.present()) {
                self.activator.activate();
            }
        }
    }

    /// Introduces a batch at an indicated level.
    ///
    /// The level indication is often related to the size of the batch, but
    /// it can also be used to artificially fuel the computation by supplying
    /// empty batches at non-trivial indices, to move merges along.
    pub fn introduce_batch(&mut self, batch: B, batch_index: usize) {

        // This spine is represented as a list of layers, where each element in the list is either
        //
        //   1. MergeState::Empty   empty
        //   2. MergeState::Single  a single batch
        //   3. MergeState::Double  : a pair of batches
        //
        // Each of the batches at layer i contains at most 2^i elements. The sequence of batches
        // should have the upper bound of one match the lower bound of the next. Batches may be
        // logically empty, with matching upper and lower bounds, as a bookkeeping mechanism.
        //
        // We attempt to maintain the invariant that no two adjacent levels have pairs of batches.
        // This invariant exists to make sure we have the breathing room to initiate but not
        // immediately complete merges. As soon as a layer contains two batches we initiate a merge
        // into a batch of the next sized layer, and we start to apply fuel to this merge. When it
        // completes, we install the newly merged batch in the next layer and uninstall the two
        // batches from their layer.
        //
        // We a merge completes, it vacates an entire level. Assuming we have maintained our invariant,
        // the number of updates below that level (say "k") is at most
        //
        //         2^k-1 + 2*2^k-2 + 2^k-3 + 2*2^k-4 + ...
        //      <=
        //         2^k+1 - 2^k-1
        //
        // Fortunately, the now empty layer k needs 2^k+1 updates before it will initiate a new merge,
        // and the collection must accept 2^k-1 updates before such a merge could possibly be initiated.
        // This means that if each introduced merge applies a proportionate amount of fuel to the merge,
        // we should be able to complete any merge at the next level before a new one is proposed.
        //
        // I believe most of this reasoning holds under the properties of the invariant that no adjacent
        // layers have two batches. This gives us the ability to do further housekeeping, especially as
        // we work with the largest layers, which we might expect not to grow in size. If at any point we
        // can tidy the largest layer downward without violating the invariant (e.g. draw it down to an
        // empty layer, or to a singleton layer and commence a merge) we should consider that in the
        // interests of maintaining a compact representation that does not grow without bounds.

        // Step 2. Apply fuel to each in-progress merge.
        //
        //         Ideally we apply fuel to the merges of the smallest
        //         layers first, as progress on these layers is important,
        //         and the sooner it happens the sooner we have fewer layers
        //         for cursors to navigate, which improves read performance.
        //
        //          It is important that by the end of this, we have ensured
        //          that position `batch_index+1` has at most a single batch,
        //          as our roll-up strategy will insert into that position.
        self.apply_fuel(self.effort << batch_index);

        // Step 1. Before installing the batch we must ensure the invariant,
        //         that no adjacent layers contain two batches. We can make
        //         this happen by forcibly completing all lower merges and
        //         integrating them with the batch itself, which can go at
        //         level index+1 as a single batch.
        //
        //         Note that this corresponds to the introduction of some
        //         volume of fake updates, and we will need to fuel merges
        //         by a proportional amount to ensure that they are not
        //         surprised later on.
        self.roll_up(batch_index);

        // Step 4. This insertion should be into an empty layer. It is a
        //         logical error otherwise, as we may be violating our
        //         invariant, from which all derives.
        self.insert_at(batch, batch_index);

        // Step 3. Tidy the largest layers.
        //
        //         It is important that we not tidy only smaller layers,
        //         as their ascension is what ensures the merging and
        //         eventual compaction of the largest layers.
        self.tidy_layers();
    }

    /// Ensures that layers up through and including `index` are empty.
    ///
    /// This method is used to prepare for the insertion of a single batch
    /// at `index`, which should maintain the invariant.
    fn roll_up(&mut self, index: usize) {

        let merge =
        self.merging[.. index+1]
            .iter_mut()
            .fold(None, |merge, level|
                match (merge, level.complete()) {
                    (Some(batch_new), Some(batch_old)) => {
                        Some(MergeState::begin_merge(batch_old, batch_new, None).complete())
                    },
                    (None, batch) => batch,
                    (merge, None) => merge,
                }
            );

        if let Some(batch) = merge {
            self.insert_at(batch, index + 1);
        }
    }

    /// Applies an amount of fuel to merges in progress.
    pub fn apply_fuel(mut fuel: usize) {

        // Scale fuel up by number of in-progress merges, or by the length of the spine.
        // We just need to make sure that the issued fuel is applied to each in-progress
        // merge, by the time its layer is needed to accept a new merge.

        fuel *= self.merging.len();
        for index in 0 .. self.merging.len() {
            if let Some(batch) = self.merging.work(&mut fuel) {
                self.insert_at(batch, index+1);
            }
        }
    }

    /// Inserts a batch at a specific location.
    ///
    /// This is a non-public internal method that can panic if we try and insert into a
    /// layer which already contains two batches (and is in the process of merging).
    fn insert_at(&mut self, batch: B, index: usize) {
        while self.merging.len() <= index {
            self.merging.push(MergeState::Empty);
        }
        let frontier = if index == self.merging.len()-1 { Some(self.advance_frontier.clone()) } else { None };
        self.merging[index].insert(batch, frontier);
    }

    /// Attempts to draw down large layers to size appropriate layers.
    fn tidy_layers(&mut self) {

        // If the largest layer is complete (not merging), we can attempt
        // to draw it down to the next layer if either that layer is empty,
        // or if it is a singleton and the layer below it is not merging.
        // We expect this should happen at various points if we have enough
        // fuel rolling around.

        let done = false;
        while !done {

        }

    }

}

/// Describes the state of a layer.
///
/// A layer can be empty, contain a single batch, or contain a pair of batches that are in the process
/// of merging into a batch for the next layer.
enum MergeState<K, V, T, R, B: Batch<K, V, T, R>> {
    /// An empty layer, containing no updates.
    Empty,
    /// A layer containing a single batch.
    Single(B),
    /// A layer containing two batch, in the process of merging.
    Double(B, B, Option<Vec<T>>, <B as Batch<K,V,T,R>>::Merger),
}

impl<K, V, T: Eq, R, B: Batch<K, V, T, R>> MergeState<K, V, T, R, B> {

    /// Immediately complete any merge.
    ///
    /// This consumes the layer, though we should probably consider returning the resources of the
    /// underlying source batches if we can manage that.
    fn complete(&mut self) -> Option<B>  {
        match std::mem::replace(self, MergeState::Empty) {
            Empty => None,
            Single(batch) => Some(batch),
            Double(b1, b2, frontier, merge) => {
                let mut fuel = usize::max_value();
                in_progress.work(source1, source2, frontier, &mut fuel);
                assert!(fuel > 0);
                let finished = finished.done();
                // logger.as_ref().map(|l|
                //     l.log(::logging::MergeEvent {
                //         operator,
                //         scale,
                //         length1: b1.len(),
                //         length2: b2.len(),
                //         complete: Some(finished.len()),
                //     })
                // );
                Some(finished)
            },
        }
    }

    fn work(&mut self, fuel: &mut usize) -> Option<B> {
        match std::mem::replace(self, MergeState::Empty) {
            MergeState::Double(b1, b2, frontier, merge) => {
                merge.work(b1, b2, frontier, fuel);
                if fuel > 0 {
                    let finished = finished.done();
                    // logger.as_ref().map(|l|
                    //     l.log(::logging::MergeEvent {
                    //         operator,
                    //         scale,
                    //         length1: b1.len(),
                    //         length2: b2.len(),
                    //         complete: Some(finished.len()),
                    //     })
                    // );
                    Some(finished)
                }
            }
            _ => None,
        }
    }

    /// Extract the merge state, often temporarily.
    fn take(&mut self) -> MergeState {
        std::mem::replace(self, MergeState::Empty)
    }

    /// Inserts a batch and begins a merge if needed.
    fn insert(&mut self, batch: B, frontier: Option<Vec<T>>) {
        match self.take() {
            Empty => { *self = MergeState::Single(batch); },
            Single(batch_old) => {
                *self = MergeState::begin_merge(batch_old, batch, frontier);
            }
            Double(_,_,_,_) => {
                panic!("Attempted to insert batch into incomplete merge!");
            }
        };
    }

    fn is_complete(&self) -> bool {
        match *self {
            MergeState::Complete(_) => true,
            _ => false,
        }
    }
    fn begin_merge(batch1: B, batch2: B, frontier: Option<Vec<T>>) -> Self {
        // logger.as_ref().map(|l| l.log(
        //     ::logging::MergeEvent {
        //         operator,
        //         scale,
        //         length1: batch1.len(),
        //         length2: batch2.len(),
        //         complete: None,
        //     }
        // ));
        assert!(batch1.upper() == batch2.lower());
        let begin_merge = <B as Batch<K, V, T, R>>::begin_merge(&batch1, &batch2);
        MergeState::Merging(batch1, batch2, frontier, begin_merge)
    }
    fn work(mut self, fuel: &mut usize) -> Self {
        if let MergeState::Merging(ref source1, ref source2, ref frontier, ref mut in_progress) = self {
            in_progress.work(source1, source2, frontier, fuel);
        }
        if *fuel > 0 {
            match self {
                // ALLOC: Here is where we may de-allocate batches.
                MergeState::Merging(b1, b2, _, finished) => {
                    let finished = finished.done();
                    // logger.as_ref().map(|l|
                    //     l.log(::logging::MergeEvent {
                    //         operator,
                    //         scale,
                    //         length1: b1.len(),
                    //         length2: b2.len(),
                    //         complete: Some(finished.len()),
                    //     })
                    // );
                    MergeState::Complete(finished)
                },
                MergeState::Complete(x) => MergeState::Complete(x),
            }
        }
        else { self }
    }
    fn len(&self) -> usize {
        match *self {
            MergeState::Merging(ref batch1, ref batch2, _, _) => batch1.len() + batch2.len(),
            MergeState::Complete(ref batch) => batch.len(),
        }
    }
}<|endoftext|>


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

/*!
 * A simple map based on a vector for small integer keys. Space requirements
 * are O(highest integer key).
 */
#[forbid(deprecated_mode)];

use core::container::{Container, Mutable, Map, Set};
use core::dvec::DVec;
use core::ops;
use core::option::{Some, None};
use core::option;
use core::prelude::*;

// FIXME (#2347): Should not be @; there's a bug somewhere in rustc that
// requires this to be.
struct SmallIntMap_<T> {
    v: DVec<Option<T>>,
}

pub enum SmallIntMap<T> {
    SmallIntMap_(@SmallIntMap_<T>)
}

/// Create a smallintmap
pub fn mk<T: Copy>() -> SmallIntMap<T> {
    let v = DVec();
    SmallIntMap_(@SmallIntMap_ { v: v } )
}

/**
 * Add a value to the map. If the map already contains a value for
 * the specified key then the original value is replaced.
 */
#[inline(always)]
pub fn insert<T: Copy>(self: SmallIntMap<T>, key: uint, val: T) {
    //io::println(fmt!("%?", key));
    self.v.grow_set_elt(key, &None, Some(val));
}

/**
 * Get the value for the specified key. If the key does not exist
 * in the map then returns none
 */
pub pure fn find<T: Copy>(self: SmallIntMap<T>, key: uint) -> Option<T> {
    if key < self.v.len() { return self.v.get_elt(key); }
    return None::<T>;
}

/**
 * Get the value for the specified key
 *
 * # Failure
 *
 * If the key does not exist in the map
 */
pub pure fn get<T: Copy>(self: SmallIntMap<T>, key: uint) -> T {
    match find(self, key) {
      None => {
        error!("smallintmap::get(): key not present");
        fail;
      }
      Some(move v) => return v
    }
}

/// Returns true if the map contains a value for the specified key
pub pure fn contains_key<T: Copy>(self: SmallIntMap<T>, key: uint) -> bool {
    return !find(self, key).is_none();
}

impl<V> SmallIntMap<V>: Container {
    /// Return the number of elements in the map
    pure fn len(&self) -> uint {
        let mut sz = 0u;
        for self.v.each |item| {
            match *item {
              Some(_) => sz += 1u,
              _ => ()
            }
        }
        sz
    }

    /// Return true if the map contains no elements
    pure fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<V> SmallIntMap<V>: Mutable {
    fn clear(&mut self) { self.v.set(~[]) }
}

/// Implements the map::map interface for smallintmap
impl<V: Copy> SmallIntMap<V> {
    #[inline(always)]
    fn insert(key: uint, value: V) -> bool {
        let exists = contains_key(self, key);
        insert(self, key, value);
        return !exists;
    }
    fn remove(key: uint) -> bool {
        if key >= self.v.len() {
            return false;
        }
        let old = self.v.get_elt(key);
        self.v.set_elt(key, None);
        old.is_some()
    }
    pure fn contains_key(key: uint) -> bool {
        contains_key(self, key)
    }
    pure fn contains_key_ref(key: &uint) -> bool {
        contains_key(self, *key)
    }
    pure fn get(key: uint) -> V { get(self, key) }
    pure fn find(key: uint) -> Option<V> { find(self, key) }

    fn update_with_key(key: uint, val: V, ff: fn(uint, V, V) -> V) -> bool {
        match self.find(key) {
            None            => return self.insert(key, val),
            Some(copy orig) => return self.insert(key, ff(key, orig, val)),
        }
    }

    fn update(key: uint, newval: V, ff: fn(V, V) -> V) -> bool {
        return self.update_with_key(key, newval, |_k, v, v1| ff(v,v1));
    }

    pure fn each(it: fn(key: uint, value: V) -> bool) {
        self.each_ref(|k, v| it(*k, *v))
    }
    pure fn each_key(it: fn(key: uint) -> bool) {
        self.each_ref(|k, _v| it(*k))
    }
    pure fn each_value(it: fn(value: V) -> bool) {
        self.each_ref(|_k, v| it(*v))
    }
    pure fn each_ref(it: fn(key: &uint, value: &V) -> bool) {
        let mut idx = 0u, l = self.v.len();
        while idx < l {
            match self.v.get_elt(idx) {
              Some(ref elt) => if !it(&idx, elt) { break },
              None => ()
            }
            idx += 1u;
        }
    }
    pure fn each_key_ref(blk: fn(key: &uint) -> bool) {
        self.each_ref(|k, _v| blk(k))
    }
    pure fn each_value_ref(blk: fn(value: &V) -> bool) {
        self.each_ref(|_k, v| blk(v))
    }
}

impl<V: Copy> SmallIntMap<V>: ops::Index<uint, V> {
    pure fn index(&self, key: uint) -> V {
        unsafe {
            get(*self, key)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{mk, SmallIntMap};

    use core::option::None;

    #[test]
    fn test_len() {
        let mut map = mk();
        assert map.len() == 0;
        assert map.is_empty();
        map.insert(5, 20);
        assert map.len() == 1;
        assert !map.is_empty();
        map.insert(11, 12);
        assert map.len() == 2;
        assert !map.is_empty();
        map.insert(14, 22);
        assert map.len() == 3;
        assert !map.is_empty();
    }

    #[test]
    fn test_clear() {
        let mut map = mk();
        map.insert(5, 20);
        map.insert(11, 12);
        map.insert(14, 22);
        map.clear();
        assert map.is_empty();
        assert map.find(5).is_none();
        assert map.find(11).is_none();
        assert map.find(14).is_none();
    }

    #[test]
    fn test_insert_with_key() {
        let map: SmallIntMap<uint> = mk();

        // given a new key, initialize it with this new count, given
        // given an existing key, add more to its count
        fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        fn addMoreToCount_simple(v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        // count integers
        map.update(3, 1, addMoreToCount_simple);
        map.update_with_key(9, 1, addMoreToCount);
        map.update(3, 7, addMoreToCount_simple);
        map.update_with_key(5, 3, addMoreToCount);
        map.update_with_key(3, 2, addMoreToCount);

        // check the total counts
        assert map.find(3).get() == 10;
        assert map.find(5).get() == 3;
        assert map.find(9).get() == 1;

        // sadly, no sevens were counted
        assert None == map.find(7);
    }
}
<|endoftext|>


<commit_before><commit_msg>Adding tests for bot<commit_after>extern crate teleborg;
extern crate reqwest;

#[cfg(test)]
mod tests {
    use teleborg::bot::{Bot, ParseMode};
    use reqwest::Client;

    use std::env;

    const BASE_URL: &'static str = "https://api.telegram.org/bot";

    fn setup() -> (String, i64) {
        let token = env::var("TELEGRAM_BOT_TOKEN")
            .ok()
            .expect("Can't find TELEGRAM_BOT_TOKEN env variable");
        let chat_id = env::var("TELEGRAM_CHAT_ID")
            .ok()
            .expect("Can't find TELEGRAM_CHAT_ID env variable")
            .parse::<i64>()
            .unwrap();
        (token, chat_id)
    }

    #[test]
    fn test_get_me() {
        let (token, _) = setup();
        let bot_url = [BASE_URL, &token].concat();
        let client = Client::new().unwrap();
        let json = Bot::get_me(&client, &bot_url);
        assert!(json.is_ok());
    }

    #[test]
    fn test_send_message() {
        let (token, chat_id) = setup();
        let bot_url = [BASE_URL, &token].concat();
        let bot = Bot::new(bot_url).unwrap();
        let message = bot.send_message(&chat_id, "test", None, None, None, None);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_text_message() {
        let (token, chat_id) = setup();
        let bot_url = [BASE_URL, &token].concat();
        let bot = Bot::new(bot_url).unwrap();
        let message = bot.send_message(&chat_id, "test", Some(&ParseMode::Text), None, None, None);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_markdown_message() {
        let (token, chat_id) = setup();
        let bot_url = [BASE_URL, &token].concat();
        let bot = Bot::new(bot_url).unwrap();
        let message = bot.send_message(&chat_id,
                                       "*test*",
                                       Some(&ParseMode::Markdown),
                                       None,
                                       None,
                                       None);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_html_message() {
        let (token, chat_id) = setup();
        let bot_url = [BASE_URL, &token].concat();
        let bot = Bot::new(bot_url).unwrap();
        let message = bot.send_message(&chat_id,
                                       "<b>test</b>",
                                       Some(&ParseMode::Html),
                                       None,
                                       None,
                                       None);
        assert!(message.is_ok());
    }
}
<|endoftext|>


<commit_before><commit_msg>Use a 'Sync' type for the session key.<commit_after><|endoftext|>


<commit_before><commit_msg>Fix the framebuffer attachment Vulkan validation layer warning relating to the usage bits for a texture<commit_after><|endoftext|>


<commit_before><commit_msg>Add utility functions for snake and camel case<commit_after>use std::ascii::AsciiExt;

pub fn camel_case(name: &str) -> String {
    let mut s = String::new();
    let mut last = ' ';
    for c in name.chars() {
        if !c.is_alphabetic() {
            last = c;
            continue;
        }
        if !c.is_ascii() {
            last = c;
            continue;
        }
        if (!last.is_alphabetic() && c.is_alphabetic()) || (last.is_lowercase() && c.is_uppercase()) {
            s.push(c.to_ascii_uppercase());
        } else {
            s.push(c.to_ascii_lowercase());
        }
        last = c;
    }
    s
}

pub fn snake_case(name: &str) -> String {
    let mut s = String::new();
    let mut last = 'A';
    for c in name.chars() {
        if !c.is_alphabetic() {
            last = c;
            continue;
        }
        if !c.is_ascii() {
            last = c;
            continue;
        }
        if (!last.is_alphabetic() && c.is_alphabetic()) || (last.is_lowercase() && c.is_uppercase()) {
            s.push('_');
        }
        s.push(c.to_ascii_lowercase());
        last = c;
    }
    s
}

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

    #[test]
    fn test_camel_case() {
        assert_eq!("FooBar", &camel_case("FooBar"));
        assert_eq!("FooBar", &camel_case("fooBar"));
        assert_eq!("FooBar", &camel_case("foo bar"));
        assert_eq!("FooBar", &camel_case("foo_bar"));
        assert_eq!("FooBar", &camel_case("FOO_BAR"));
    }

    #[test]
    fn test_snake_case() {
        assert_eq!("foo_bar", &snake_case("FooBar"));
        assert_eq!("foo_bar", &snake_case("fooBar"));
        assert_eq!("foo_bar", &snake_case("foo bar"));
        assert_eq!("foo_bar", &snake_case("foo_bar"));
        assert_eq!("foo_bar", &snake_case("FOO_BAR"));
    }
}
<|endoftext|>


<commit_before><commit_msg>add doc<commit_after><|endoftext|>


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

pub trait Borrow<Sized? Borrowed> {
        fn borrow(&self) -> &Borrowed;
}

impl<T: Sized> Borrow<T> for T {
        fn borrow(&self) -> &T { self }
}

trait Foo {
        fn foo(&self, other: &Self);
}

fn bar<K, Q>(k: &K, q: &Q) where K: Borrow<Q>, Q: Foo {
    q.foo(k.borrow())
}

struct MyTree<K>;

impl<K> MyTree<K> {
    // This caused a failure in #18906
    fn bar<Q>(k: &K, q: &Q) where K: Borrow<Q>, Q: Foo {
        q.foo(k.borrow())
    }
}

fn main() {}
<|endoftext|>


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

fn main() {
    let x: &'static str = "x";

    {
        let y = "y".to_string();
        let ref mut x = &*x;
        *x = &*y;
    }

    assert_eq!(x, "x");
}
<|endoftext|>


<commit_before><commit_msg>Add test to confirm that Cargo.toml.orig files are reserved.<commit_after><|endoftext|>


<commit_before><commit_msg>Add 2015 day 25 solution<commit_after>#[derive(Debug, Copy, Clone, PartialEq)]
struct Pos(usize, usize);

struct CodeIterator {
    value: Option<u64>
}

impl CodeIterator {
    fn new() -> CodeIterator {
        CodeIterator {value: None}
    }
}

impl Iterator for CodeIterator {
    type Item = u64;

    fn next(&mut self) -> Option<Self::Item> {
        self.value = Some(match self.value {
            None => 20151125,
            Some(x) => (x * 252533) % 33554393
        });

        self.value.clone()
    }
}

fn pos_to_index(Pos(row, col): Pos) -> usize {
    let level = row + col - 1;
    (1..level).sum::<usize>() + col - 1
}

fn main() {
    let input = Pos(2981, 3075);
    let index = pos_to_index(input);
    let mut code_iterator = CodeIterator::new();

    println!("Part 1: {}", code_iterator.nth(index).unwrap());
}
<|endoftext|>


<commit_before><commit_msg>Update to current rust: std::vec -> std::slice.<commit_after><|endoftext|>


<commit_before><commit_msg>feat(geektime_algo): add 32 string, BF and RK<commit_after>use std::collections::HashMap;

fn bf(primary: &str, pattern: &str) -> i32 {
    if primary.is_empty() || pattern.is_empty() || primary.len() < pattern.len() { return -1; }

    let primary_chars: Vec<char> = primary.chars().collect();
    let pattern_chars: Vec<char> = pattern.chars().collect();
    for i in 0..(primary.len() - pattern.len() + 1) {
        if pattern_chars == primary_chars[i..i + pattern.len()].to_vec() {
            return i as i32;
        }
    }
    -1
}

// 通过哈希算法对主串中的 n-m+1 个子串分别求哈希值，
// 逐个与模式串的哈希值比较大小。如果某个子串的哈希值与模式串相等，那就说明对应的子串和模式串匹配
fn rk(primary: &str, pattern: &str) -> i32 {
    if primary.is_empty() || pattern.is_empty() || primary.len() < pattern.len() { return -1; }

    let primary_chars: Vec<char> = primary.chars().collect();
    let pattern_chars: Vec<char> = pattern.chars().collect();
    let base: i128 = 26;
    let m = pattern.len();
    let n = primary.len();
    let mut pow_vec = vec![];
    let mut hash = HashMap::new();

    // 存储 26 的 n 次方到数组中，方便后面调用
    for i in 0..m {
        pow_vec.push(base.pow(i as u32));
    }

    // 计算子串的 hash 值
    let mut p_value = 0;
    for i in 0..m {
        p_value += (pattern_chars[i] as i128 - 'a' as i128) * pow_vec[m-1-i];
    }

    // 计算主串的 n-m+1 个子串的 hash 值
    for i in 0..(n - m + 1) {
        // 计算主串中 index 为 0 的子串的 hash 值
        let mut value = 0;
        if i == 0 {
            for i in 0..m {
                value += (primary_chars[i] as i128 - 'a' as i128) * pow_vec[m-1-i];
            }
        } else {
            // 计算 index 为 i 的子串的 hash 值
            // 计算公式: hash[i] = (hash[i-1] - 26^(m-1) * (primary_chars[i-1] - 'a')) * 26 + (26^0 * (primary_chars[i+m-1] - 'a'))
            value = (hash[&((i-1) as i32)] - base.pow((m-1) as u32) * (primary_chars[i-1] as i128 - 'a' as i128)) * base + ((primary_chars[i+m-1]) as i128 - 'a' as i128);
        }

        // hash 值相等，比较两个串内容是否相等，避免 hash 碰撞
        if value == p_value && pattern_chars == primary_chars[i..i+m].to_vec() {
            return i as i32;
        }

        hash.insert(i as i32, value);
    }

    -1
}

fn main() {
    let primary = "thequickbrownfoxjumpsoverthelazydog";
    let pattern = "jump";
    let result = bf(primary, pattern);
    println!("{}", result); // 16

    let result2 = rk(primary, pattern);
    println!("{:?}", result2); // 16
}
<|endoftext|>


<commit_before><commit_msg>no_std testcase<commit_after>// requires nightly toolchain!
#![no_std]
#![feature(collections)]
#![allow(dead_code)]

#[macro_use]
extern crate derive_builder;
extern crate collections;

#[derive(Builder)]
#[builder(no_std)]
struct IgnoreEmptyStruct {}
<|endoftext|>


<commit_before><commit_msg>nbody example<commit_after>use stdsimd::simd::*;

use std::f64::consts::PI;
const SOLAR_MASS: f64 = 4.0 * PI * PI;
const DAYS_PER_YEAR: f64 = 365.24;

pub struct Body {
    pub x: f64x4,
    pub v: f64x4,
    pub mass: f64,
}
const N_BODIES: usize = 5;
#[allow(clippy::unreadable_literal)]
const BODIES: [Body; N_BODIES] = [
    // sun:
    Body {
        x: f64x4::new(0., 0., 0., 0.),
        v: f64x4::new(0., 0., 0., 0.),
        mass: SOLAR_MASS,
    },
    // jupiter:
    Body {
        x: f64x4::new(
            4.84143144246472090e+00,
            -1.16032004402742839e+00,
            -1.03622044471123109e-01,
            0.,
        ),
        v: f64x4::new(
            1.66007664274403694e-03 * DAYS_PER_YEAR,
            7.69901118419740425e-03 * DAYS_PER_YEAR,
            -6.90460016972063023e-05 * DAYS_PER_YEAR,
            0.,
        ),
        mass: 9.54791938424326609e-04 * SOLAR_MASS,
    },
    // saturn:
    Body {
        x: f64x4::new(
            8.34336671824457987e+00,
            4.12479856412430479e+00,
            -4.03523417114321381e-01,
            0.,
        ),
        v: f64x4::new(
            -2.76742510726862411e-03 * DAYS_PER_YEAR,
            4.99852801234917238e-03 * DAYS_PER_YEAR,
            2.30417297573763929e-05 * DAYS_PER_YEAR,
            0.,
        ),
        mass: 2.85885980666130812e-04 * SOLAR_MASS,
    },
    // uranus:
    Body {
        x: f64x4::new(
            1.28943695621391310e+01,
            -1.51111514016986312e+01,
            -2.23307578892655734e-01,
            0.,
        ),
        v: f64x4::new(
            2.96460137564761618e-03 * DAYS_PER_YEAR,
            2.37847173959480950e-03 * DAYS_PER_YEAR,
            -2.96589568540237556e-05 * DAYS_PER_YEAR,
            0.,
        ),
        mass: 4.36624404335156298e-05 * SOLAR_MASS,
    },
    // neptune:
    Body {
        x: f64x4::new(
            1.53796971148509165e+01,
            -2.59193146099879641e+01,
            1.79258772950371181e-01,
            0.,
        ),
        v: f64x4::new(
            2.68067772490389322e-03 * DAYS_PER_YEAR,
            1.62824170038242295e-03 * DAYS_PER_YEAR,
            -9.51592254519715870e-05 * DAYS_PER_YEAR,
            0.,
        ),
        mass: 5.15138902046611451e-05 * SOLAR_MASS,
    },
];

pub fn offset_momentum(bodies: &mut [Body; N_BODIES]) {
    let (sun, rest) = bodies.split_at_mut(1);
    let sun = &mut sun[0];
    for body in rest {
        let m_ratio = body.mass / SOLAR_MASS;
        sun.v -= body.v * m_ratio;
    }
}

pub fn energy(bodies: &[Body; N_BODIES]) -> f64 {
    let mut e = 0.;
    for i in 0..N_BODIES {
        let bi = &bodies[i];
        e += bi.mass * (bi.v * bi.v).sum() * 0.5;
        for bj in bodies.iter().take(N_BODIES).skip(i + 1) {
            let dx = bi.x - bj.x;
            e -= bi.mass * bj.mass / (dx * dx).sum().sqrt()
        }
    }
    e
}

pub fn advance(bodies: &mut [Body; N_BODIES], dt: f64) {
    const N: usize = N_BODIES * (N_BODIES - 1) / 2;

    // compute distance between bodies:
    let mut r = [f64x4::splat(0.); N];
    {
        let mut i = 0;
        for j in 0..N_BODIES {
            for k in j + 1..N_BODIES {
                r[i] = bodies[j].x - bodies[k].x;
                i += 1;
            }
        }
    }

    let mut mag = [0.0; N];
    let mut i = 0;
    while i < N {
        let d2s = f64x2::new((r[i] * r[i]).sum(), (r[i + 1] * r[i + 1]).sum());
        let dmags = f64x2::splat(dt) / (d2s * d2s.sqrte());
        dmags.write_to_slice_unaligned(&mut mag[i..]);
        i += 2;
    }

    i = 0;
    for j in 0..N_BODIES {
        for k in j + 1..N_BODIES {
            let f = r[i] * mag[i];
            bodies[j].v -= f * bodies[k].mass;
            bodies[k].v += f * bodies[j].mass;
            i += 1
        }
    }
    for body in bodies {
        body.x += dt * body.v
    }
}

pub fn run_k<K>(n: usize, k: K) -> (f64, f64)
where
    K: Fn(&mut [Body; N_BODIES], f64),
{
    let mut bodies = BODIES;
    offset_momentum(&mut bodies);
    let energy_before = energy(&bodies);
    for _ in 0..n {
        k(&mut bodies, 0.01);
    }
    let energy_after = energy(&bodies);

    (energy_before, energy_after)
}

pub fn run(n: usize) -> (f64, f64) {
    run_k(n, advance)
}

const OUTPUT: Vec<f64> = vec![-0.169075164, -0.169087605];
#[cfg(test)]
mod tests {
    #[test]
    fn test() {
        let mut out: Vec<u8> = Vec::new();
        run(&mut out, 1000, 0);
        for &(size, a_e, b_e) in crate::RESULTS {
            let (a, b) = super::run(size);
            assert_eq!(format!("{:.9}", a), a_e);
            assert_eq!(format!("{:.9}", b), b_e);
        }
    }
}
fn main() {
    //let n: usize = std::env::args()
    //.nth(1)
    //.expect("need one arg")
    //.parse()
    //.expect("argument should be a usize");
    //run(&mut std::io::stdout(), n, alg);
    println!("{:?}", run_k<10>(10, 10));
}
<|endoftext|>


<commit_before><commit_msg>Add a simple build.rs to the examples.<commit_after>#![feature(fs_time)]

use std::process::Command;

fn main() {
    for f in  std::fs::read_dir("src").unwrap() {
        let name = f.unwrap().path();
        if name.extension() == Some("y".as_ref()) {
            let name_rs = name.with_extension("rs");

            let meta_y = std::fs::metadata(&name).unwrap();
            let need_to_build = match std::fs::metadata(&name_rs) {
                Ok(x) => x.modified() < meta_y.modified(),
                Err(_) => true,
            };
            if need_to_build {
                Command::new("../../lemon_rust").arg(&name)
                    .status().unwrap();
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Added custom class example.<commit_after>#![feature(phase)]

#[phase(plugin, link)]
extern crate objc;

use objc::{class, ClassDecl, Id};
use objc::runtime::Object;
use objc::foundation::{INSObject, NSObject};

object_struct!(MYObject)

impl MYObject {
	fn number(&self) -> uint {
		let obj = unsafe {
			&*(self as *const _ as *const Object)
		};
		unsafe {
			*obj.get_ivar::<uint>("_number")
		}
	}

	fn set_number(&mut self, number: uint) {
		let obj = unsafe {
			&mut *(self as *mut _ as *mut Object)
		};
		unsafe {
			obj.set_ivar("_number", number);
		}
	}

	fn register() {
		let superclass = class::<NSObject>();
		let mut decl = ClassDecl::new(superclass, "MYObject").unwrap();

		decl.add_ivar::<uint>("_number");
		decl.add_method(method!(
			(&mut MYObject)this, setNumber:(uint)number; {
				this.set_number(number);
			}
		));
		decl.add_method(method!(
			(&MYObject)this, number -> uint {
				this.number()
			}
		));

		decl.register();
	}
}

fn main() {
	MYObject::register();
	let mut obj: Id<MYObject> = INSObject::new();
	println!("{}", obj);

	obj.deref_mut().set_number(7);
	println!("Number: {}", obj.number());

	unsafe {
		msg_send![obj setNumber:12u];
	}
	println!("Number: {}", obj.number());
}
<|endoftext|>


<commit_before><commit_msg>Add a disassembler example<commit_after>//! Sample of disassembler library usage.
//!
//! The LLVM disassembler takes bytes and an assumed value for the program
//! counter, emitting instructions as strings.
//!
//! This example takes bytes on stdin and emits text instructions on stdout.

extern crate llvm_sys;

use std::ffi::CStr;
use std::io::{Result as IoResult, Read, Write, stdin, stdout};
use std::ptr;
use llvm_sys::disassembler::{LLVMDisasmContextRef, LLVMCreateDisasm, LLVMDisasmDispose, LLVMDisasmInstruction};
use llvm_sys::target::{LLVM_InitializeAllDisassemblers, LLVM_InitializeAllTargetInfos, LLVM_InitializeAllTargetMCs};

fn main() -> IoResult<()> {
    let disasm = unsafe {
        LLVM_InitializeAllTargetInfos();
        LLVM_InitializeAllTargetMCs();
        LLVM_InitializeAllDisassemblers();
        LLVMCreateDisasm("x86_64\0".as_ptr() as *const i8, ptr::null_mut(), 0, None, None)
    };
    if disasm.is_null() {
        eprintln!("Failed to create disassembler");
        return Ok(());
    }

    let mut data = Vec::<u8>::new();
    stdin().read_to_end(&mut data)?;
    let r = disassemble_bytes(&mut data, disasm, stdout());

    unsafe {
        LLVMDisasmDispose(disasm);
    }

    r
}

const PC_BASE_ADDR: u64 = 0;

fn disassemble_bytes<W: Write>(mut x: &mut [u8], disasm: LLVMDisasmContextRef, mut out: W) -> IoResult<()> {
    let mut pc = PC_BASE_ADDR;

    loop {
        let mut sbuf = [0i8; 128];
        let sz = unsafe {
            LLVMDisasmInstruction(disasm, x.as_mut_ptr(), x.len() as u64, pc, sbuf.as_mut_ptr() as *mut i8, sbuf.len())
        };
        if sz == 0 {
            break;
        }

        let instr_str = unsafe {
            CStr::from_ptr(sbuf.as_ptr())
        };
        write!(out, "{}\n", instr_str.to_string_lossy())?;

        pc += sz as u64;
        x = &mut x[sz..];
    }

    Ok(())
}
<|endoftext|>


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

trait I { fn i(&self) -> Self; }

trait A<T:I> {
    fn id(x:T) -> T { x.i() }
}

trait J<T> { fn j(&self) -> Self; }

trait B<T:J<T>> {
    fn id(x:T) -> T { x.j() }
}

trait C {
    fn id<T:J<T>>(x:T) -> T { x.j() }
}

fn main() { }
<|endoftext|>


<commit_before><commit_msg>Added "resources" example<commit_after>/*
Demonstrates a pattern where resources of types
are connected to the associated types of various traits.

The individual traits can be implemented separately from the backend.
A `Resources` trait has a role of integrating the types from various traits.

This pattern can be used when associated types are shared across backends.
*/

#[macro_use]
extern crate backend;

pub trait Resources {
    type Vec2;
}

pub trait VecMath {
    type Vec2;

    fn add_vec2(&self, a: Self::Vec2, b: Self::Vec2) -> Self::Vec2;
}

backend!(
    Resources [Resources],
    VecMath [VecMath<Vec2 = <Self::Resources as Resources>::Vec2>]
);

pub struct Math;

backend_impl!(
    Math {
        Resources, VecMath = Math
    }
);

impl Resources for Math {
    type Vec2 = [f64; 2];
}

impl VecMath for Math {
    type Vec2 = [f64; 2];

    fn add_vec2(&self, a: [f64; 2], b: [f64; 2]) -> [f64; 2] {
        [a[0] + b[0], a[1] + b[1]]
    }
}

fn add<V: VecMath>(v: &V, a: V::Vec2, b: V::Vec2) -> V::Vec2 {
    v.add_vec2(a, b)
}

pub fn main() {
    let res = Math.add_vec2([0.0, 1.0], [1.0, 0.0]);
    let res2 = add(&Math, [0.0, 1.0], [1.0, 0.0]);
    assert_eq!(res, res2);
}
<|endoftext|>


<commit_before><commit_msg>fixed build on msys<commit_after><|endoftext|>


<commit_before><commit_msg>New mod dxgi_enumerations<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Johan Johansson
//
// 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.

//! Enumerations provided by DXGI.
//!
//! # References
//! [DXGI Enumerations, MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471320(v=vs.85).aspx)

<|endoftext|>


<commit_before><commit_msg>Add some more details to the comment regarding repeated creation of new rendering threads<commit_after><|endoftext|>


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

use io::ReaderUtil;
pub fn main() {
    let mut x: bool = false;
    // this line breaks it
    vec::rusti::move_val_init(&mut x, false);

    let input = io::stdin();
    let line = input.read_line(); // use core's io again

    io::println(fmt!("got %?", line));
}
<commit_msg>auto merge of #5000 : jld/rust/test-stdin-thing, r=graydon<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub fn main() {
    let mut x: bool = false;
    // this line breaks it
    vec::rusti::move_val_init(&mut x, false);
}
<|endoftext|>