<commit_before>#![feature(macro_rules)]
#![feature(globs)]

extern crate encoding;
extern crate uchardet;

use encoding::EncodingRef;
use encoding::label::encoding_from_whatwg_label;

/*
Here's a list of all the places I could find in the uchardet source which
returned a charset name.  Note that I may have missed some, and that other
versions of uchardet might add or remove character sets.

src/nsBig5Prober.h:  const char* GetCharSetName() {return "Big5";}
src/nsEUCJPProber.h:  const char* GetCharSetName() {return "EUC-JP";}
src/nsEUCKRProber.h:  const char* GetCharSetName() {return "EUC-KR";}
src/nsEUCTWProber.h:  const char* GetCharSetName() {return "x-euc-tw";}
src/nsGB2312Prober.h:  const char* GetCharSetName() {return "gb18030";}
src/nsLatin1Prober.h:  const char* GetCharSetName() {return "windows-1252";}
src/nsSJISProber.h:  const char* GetCharSetName() {return "Shift_JIS";}
src/nsUTF8Prober.h:  const char* GetCharSetName() {return "UTF-8";}

extern const SMModel UTF8SMModel; "UTF-8",
extern const SMModel Big5SMModel; "Big5",
extern const SMModel EUCJPSMModel; "EUC-JP",
extern const SMModel EUCKRSMModel; "EUC-KR",
extern const SMModel EUCTWSMModel; "x-euc-tw",
extern const SMModel GB18030SMModel; "GB18030",
extern const SMModel SJISSMModel; "Shift_JIS",
extern const SMModel HZSMModel; "HZ-GB-2312"
extern const SMModel ISO2022CNSMModel; "ISO-2022-CN"
extern const SMModel ISO2022JPSMModel; "ISO-2022-JP"
extern const SMModel ISO2022KRSMModel; "ISO-2022-KR"

#define VISUAL_HEBREW_NAME ("ISO-8859-8")
#define LOGICAL_HEBREW_NAME ("windows-1255")

mDetectedCharset = "UTF-8";
mDetectedCharset = "UTF-16";

From README.md (this is different from what the code seems to suggest):

  * Unicode
    * UTF-8
    * UTF-16BE / UTF-16LE
    * UTF-32BE / UTF-32LE / X-ISO-10646-UCS-4-34121 / X-ISO-10646-UCS-4-21431
  * Chinese
    * ISO-2022-CN
    * BIG5
    * EUC-TW
    * GB18030
    * HZ-GB-23121
  * Japanese
    * ISO-2022-JP
    * SHIFT_JIS
    * EUC-JP
  * Korean
    * ISO-2022-KR
    * EUC-KR
  * Cyrillic
    * ISO-8859-5
    * KOI8-R
    * WINDOWS-1251
    * MACCYRILLIC
    * IBM866
    * IBM855
  * Greek
    * ISO-8859-7
    * WINDOWS-1253
  * Hebrew
    * ISO-8859-8
    * WINDOWS-1255
  * Others
    * WINDOWS-1252
*/

/// Map the output of uchardet::detect_encoding_name to an `Encoding`
/// object.
pub fn encoding_from_uchardet_name(name: &str) -> Option<EncodingRef> {
    match name {
        // uchardet uses this for both UTF-16LE and UTF-16LE, so we
        // can't return an unambiguous and correct answer here.
        "UTF-16" => None,
        _ => {
            let encoding =  encoding_from_whatwg_label(name);
            match encoding {
                // SECURITY: Is this reasonable?  Rather than replacing
                // the entire input with a single replacement character,
                // and the output with UTF-8, refuse to handle the
                // encoding at all.
                Some(e) if e.name() == "encoder-only-utf-8" => None,
                _ => encoding
            }
        }
    }
}

#[cfg(test)]
mod test {
    use encoding::types::Encoding;
    use encoding::all::*;
    use self::super::*;

    macro_rules! assert_encoding_for_name {
        ($encoding:expr, $name:expr) => ({
            let expected = $encoding;
            let actual = encoding_from_uchardet_name($name);
            assert!(actual.is_some());
            assert_eq!(expected.name(), actual.unwrap().name());
        })
    }

    #[test]
    fn test_encoding_from_uchardet_name() {
        assert_encoding_for_name!(BIG5_2003, "Big5");
        assert_encoding_for_name!(EUC_JP, "EUC-JP");
        assert_encoding_for_name!(WINDOWS_949, "EUC-KR");
        assert_encoding_for_name!(GB18030, "gb18030");
        assert_encoding_for_name!(GB18030, "GB18030");
        assert_encoding_for_name!(HZ, "HZ-GB-2312");
        assert_encoding_for_name!(ISO_2022_JP, "ISO-2022-JP");
        // These encodings are allegedly used mostly for XXS.  See:
        // http://www.cvedetails.com/cve/2012-0477
        // https://encoding.spec.whatwg.org/#names-and-labels
        // https://encoding.spec.whatwg.org/#replacement
        assert!(encoding_from_uchardet_name("ISO-2022-CN").is_none());
        assert!(encoding_from_uchardet_name("ISO-2022-KR").is_none());
        assert_encoding_for_name!(ISO_8859_8, "ISO-8859-8");
        assert_encoding_for_name!(WINDOWS_31J, "Shift_JIS");
        assert_encoding_for_name!(UTF_8, "UTF-8");
        // Problem: Both BE and LE map to UTF-16.
        assert!(encoding_from_uchardet_name("UTF-16").is_none());
        assert_encoding_for_name!(WINDOWS_1252, "windows-1252");
        assert_encoding_for_name!(WINDOWS_1255, "windows-1255");
        //assert_encoding_for_name!(, "x-euc-tw");
    }
}
<commit_msg>WIP: Start roughing in more of encoding detection<commit_after>//! A highly experimental binding to rust-encoding.

#![feature(macro_rules)]
#![feature(globs)]
#![experimental]
#![warn(missing_docs)]

extern crate encoding;
extern crate uchardet;

use std::error::Error;
use encoding::EncodingRef;
use encoding::label::encoding_from_whatwg_label;

/*
Here's a list of all the places I could find in the uchardet source which
returned a charset name.  Note that I may have missed some, and that other
versions of uchardet might add or remove character sets.

src/nsBig5Prober.h:  const char* GetCharSetName() {return "Big5";}
src/nsEUCJPProber.h:  const char* GetCharSetName() {return "EUC-JP";}
src/nsEUCKRProber.h:  const char* GetCharSetName() {return "EUC-KR";}
src/nsEUCTWProber.h:  const char* GetCharSetName() {return "x-euc-tw";}
src/nsGB2312Prober.h:  const char* GetCharSetName() {return "gb18030";}
src/nsLatin1Prober.h:  const char* GetCharSetName() {return "windows-1252";}
src/nsSJISProber.h:  const char* GetCharSetName() {return "Shift_JIS";}
src/nsUTF8Prober.h:  const char* GetCharSetName() {return "UTF-8";}

extern const SMModel UTF8SMModel; "UTF-8",
extern const SMModel Big5SMModel; "Big5",
extern const SMModel EUCJPSMModel; "EUC-JP",
extern const SMModel EUCKRSMModel; "EUC-KR",
extern const SMModel EUCTWSMModel; "x-euc-tw",
extern const SMModel GB18030SMModel; "GB18030",
extern const SMModel SJISSMModel; "Shift_JIS",
extern const SMModel HZSMModel; "HZ-GB-2312"
extern const SMModel ISO2022CNSMModel; "ISO-2022-CN"
extern const SMModel ISO2022JPSMModel; "ISO-2022-JP"
extern const SMModel ISO2022KRSMModel; "ISO-2022-KR"

#define VISUAL_HEBREW_NAME ("ISO-8859-8")
#define LOGICAL_HEBREW_NAME ("windows-1255")

mDetectedCharset = "UTF-8";
mDetectedCharset = "UTF-16";

From README.md (this is different from what the code seems to suggest):

  * Unicode
    * UTF-8
    * UTF-16BE / UTF-16LE
    * UTF-32BE / UTF-32LE / X-ISO-10646-UCS-4-34121 / X-ISO-10646-UCS-4-21431
  * Chinese
    * ISO-2022-CN
    * BIG5
    * EUC-TW
    * GB18030
    * HZ-GB-23121
  * Japanese
    * ISO-2022-JP
    * SHIFT_JIS
    * EUC-JP
  * Korean
    * ISO-2022-KR
    * EUC-KR
  * Cyrillic
    * ISO-8859-5
    * KOI8-R
    * WINDOWS-1251
    * MACCYRILLIC
    * IBM866
    * IBM855
  * Greek
    * ISO-8859-7
    * WINDOWS-1253
  * Hebrew
    * ISO-8859-8
    * WINDOWS-1255
  * Others
    * WINDOWS-1252
*/

/// Returned when decoding a byte array fails.
pub enum DecodingError {
    /// We can't figure out encoding used by the input.
    EncodingUnknown,
    /// We can guess the encoding, but we can't decode it.  Note that
    /// this may be caused `encoding::all::whatwg::REPLACEMENT` being used
    /// to intercept insecure encodings.
    NoDecoder{encoding_name: String},
    /// The chosen decoder could not actually decode the input.
    DecoderFailed{encoding_name: String, message: String},
    // Other errors, the details of which are probably unimportant.
    Unexpected{cause: Box<Error+Send>}
}

impl Error for DecodingError {
    fn description(&self) -> &str { "decoding error" }

    fn detail(&self) -> Option<String> {
        use DecodingError::*;
        match self {
            &EncodingUnknown => Some("could not guess encoding".to_string()),
            &NoDecoder{encoding_name: ref name} =>
                Some(format!("no decoder for {}", name)),
            &DecoderFailed{encoding_name: ref name, message: ref msg} =>
                Some(format!("error decoding {}: {}", name, msg)),
            &Unexpected{..} => Some("unexpected error".to_string())
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
        //use DecodingError::*;
        //match self {
        //    &Unexpected{cause: cause} => Some(&*cause),
        //    _ => None
        //}
    }
}

// ```
// let data = "français".as_bytes();
// let encoding = detect_encoding(data).unwrap();
// let data.decode(DecoderTrap::Strict).unwrap();
// assert_eq!(Some("UTF-8".to_string()),
//            detect_encoding("français".as_bytes()).unwrap());
// ```
//pub fn detect_encoding(data: Vec<u8>) -> Option<EncodingRef> {
//
//}

/// Map the output of uchardet::detect_encoding_name to an `Encoding`
/// object.  Note that this has certain complications and limitations:
///
/// 1. There's no mapping for `UTF-16` because because uchardet uses
///    that value for both UTF-16LE and UTF-16BE encodings.
/// 2. The uchardet library represents "ASCII or unknown" using the
///    empty string.  We map this to `None`.
/// 3. Any legacy encoding which would map to the `Replacement` encoding
///    will return `None`.
fn encoding_from_uchardet_name(name: &str) -> Option<EncodingRef> {
    match name {
        "UTF-16" => None,
        _ => {
            let encoding =  encoding_from_whatwg_label(name);
            match encoding {
                // SECURITY: Is this reasonable?  Rather than replacing
                // the entire input with a single replacement character,
                // and the output with UTF-8, refuse to handle the
                // encoding at all.
                Some(e) if e.name() == "encoder-only-utf-8" => None,
                _ => encoding
            }
        }
    }
}

macro_rules! assert_encoding_for_name {
    ($encoding:expr, $name:expr) => ({
        let expected = $encoding;
        let actual =
            encoding_from_uchardet_name($name).expect("Expected an encoding");
        assert_eq!(expected.name(), actual.name());
    })
}

#[test]
fn test_encoding_from_uchardet_name() {
    use encoding::types::Encoding;
    use encoding::all::*;

    assert!(encoding_from_uchardet_name("").is_none());
    assert_encoding_for_name!(BIG5_2003, "Big5");
    assert_encoding_for_name!(EUC_JP, "EUC-JP");
    assert_encoding_for_name!(WINDOWS_949, "EUC-KR");
    assert_encoding_for_name!(GB18030, "gb18030");
    assert_encoding_for_name!(GB18030, "GB18030");
    assert_encoding_for_name!(HZ, "HZ-GB-2312");
    assert_encoding_for_name!(ISO_2022_JP, "ISO-2022-JP");
    // These encodings are allegedly used mostly for XXS.  See:
    // http://www.cvedetails.com/cve/2012-0477
    // https://encoding.spec.whatwg.org/#names-and-labels
    // https://encoding.spec.whatwg.org/#replacement
    assert!(encoding_from_uchardet_name("ISO-2022-CN").is_none());
    assert!(encoding_from_uchardet_name("ISO-2022-KR").is_none());
    assert_encoding_for_name!(ISO_8859_8, "ISO-8859-8");
    assert_encoding_for_name!(WINDOWS_31J, "Shift_JIS");
    assert_encoding_for_name!(UTF_8, "UTF-8");
    // Problem: Both BE and LE map to UTF-16.
    assert!(encoding_from_uchardet_name("UTF-16").is_none());
    assert_encoding_for_name!(WINDOWS_1252, "windows-1252");
    assert_encoding_for_name!(WINDOWS_1255, "windows-1255");
    //assert_encoding_for_name!(, "x-euc-tw");
}

<|endoftext|>


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

use super::SubTok;

use std::char::{to_digit, from_u32};

mod data;

pub struct CharRef {
    chars: [char, ..2],
    num_chars: u8,
    parse_error: bool,
}

pub enum Status {
    Stuck,
    Progress,
    Done,
}

enum State {
    Begin,
    Octothorpe,
    Numeric(u32), // base
    NumericSemicolon,
    Named,
}

pub struct CharRefTokenizer {
    priv state: State,
    priv addnl_allowed: Option<char>,
    priv result: Option<CharRef>,

    priv num: u32,
    priv num_too_big: bool,
    priv seen_digit: bool,
    priv hex_marker: Option<char>,

    priv name_buf: Option<~str>,
    priv last_name_match: Option<&'static [char, ..2]>,
    priv last_name_char: char,
}

impl CharRefTokenizer {
    pub fn new(addnl_allowed: Option<char>) -> CharRefTokenizer {
        CharRefTokenizer {
            state: Begin,
            addnl_allowed: addnl_allowed,
            result: None,
            num: 0,
            num_too_big: false,
            seen_digit: false,
            hex_marker: None,
            name_buf: None,
            last_name_match: None,
            last_name_char: '\0',
        }
    }

    pub fn step<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        if self.result.is_some() {
            return Done;
        }

        match self.state {
            Begin => self.do_begin(tokenizer),
            Octothorpe => self.do_octothorpe(tokenizer),
            Numeric(base) => self.do_numeric(tokenizer, base),
            NumericSemicolon => self.do_numeric_semicolon(tokenizer),
            Named => self.do_named(tokenizer),
        }
    }

    // A CharRefTokenizer can only tokenize one character reference,
    // so this method consumes the tokenizer.
    pub fn get_result(self) -> CharRef {
        self.result.expect("get_result called before done")
    }

    fn finish_none(&mut self, error: bool) -> Status {
        self.result = Some(CharRef {
            chars: ['\0', '\0'],
            num_chars: 0,
            parse_error: error,
        });
        Done
    }

    fn finish_one(&mut self, c: char, error: bool) -> Status {
        self.result = Some(CharRef {
            chars: [c, '\0'],
            num_chars: 1,
            parse_error: error,
        });
        Done
    }

    fn do_begin<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        match unwrap_or_return!(tokenizer.peek(), Stuck) {
            '\t' | '\n' | '\x0C' | ' ' | '<' | '&'
                => self.finish_none(false),
            c if Some(c) == self.addnl_allowed
                => self.finish_none(false),

            '#' => {
                tokenizer.discard_char();
                self.state = Octothorpe;
                Progress
            }

            _ => {
                self.state = Named;
                self.name_buf = Some(~"");
                Progress
            }
        }
    }

    fn do_octothorpe<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        match c {
            'x' | 'X' => {
                tokenizer.discard_char();
                self.hex_marker = Some(c);
                self.state = Numeric(16);
            }

            _ => {
                self.hex_marker = None;
                self.state = Numeric(10);
            }
        }
        Progress
    }

    fn do_numeric<T: SubTok>(&mut self, tokenizer: &mut T, base: u32) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        match to_digit(c, base as uint) {
            Some(n) => {
                tokenizer.discard_char();
                self.num *= base;
                if self.num > 0x10FFFF {
                    // We might overflow, and the character is definitely invalid.
                    // We still parse digits and semicolon, but don't use the result.
                    self.num_too_big = true;
                }
                self.num += n as u32;
                self.seen_digit = true;
                Progress
            }

            None if !self.seen_digit => {
                let mut unconsume = ~"#";
                match self.hex_marker {
                    Some(c) => unconsume.push_char(c),
                    None => (),
                }

                tokenizer.unconsume(unconsume);
                self.finish_none(true)
            }

            None => {
                self.state = NumericSemicolon;
                Progress
            }
        }
    }

    fn do_numeric_semicolon<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        fn conv(n: u32) -> char {
            from_u32(n).expect("invalid char missed by error handling cases")
        }

        let semi_missing = match unwrap_or_return!(tokenizer.peek(), Stuck) {
            ';' => { tokenizer.discard_char(); false }
            _   => true
        };

        match self.num {
            n if (n > 0x10FFFF) || self.num_too_big => self.finish_one('\ufffd', true),
            0x00 | 0xD800..0xDFFF => self.finish_one('\ufffd', true),

            0x80..0x9F => match data::c1_replacements[self.num - 0x80] {
                Some(c) => self.finish_one(c, true),
                None => self.finish_one(conv(self.num), semi_missing),
            },

            0x01..0x08 | 0x0D..0x1F | 0x7F..0x9F | 0xFDD0..0xFDEF | 0x0B
                => self.finish_one(conv(self.num), true),

            n if (n & 0xFFFE) == 0xFFFE
                => self.finish_one(conv(n), true),

            n => self.finish_one(conv(n), semi_missing),
        }
    }

    fn do_named<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        self.name_buf.get_mut_ref().push_char(c);
        match data::named_entities.find(&self.name_buf.get_ref().as_slice()) {
            Some(m) => {
                // The buffer matches an entity, or a prefix of an entity.  In
                // the latter case, both chars in last_name_match are \0.
                tokenizer.discard_char();
                self.last_name_match = Some(m);
                self.last_name_char = c;
                Progress
            }

            // Can't continue the match.
            None => match self.last_name_match {
                None | Some(&['\0', _]) => {
                    // We matched nothing, or a prefix only.
                    //
                    // FIXME: "if the characters after the U+0026 AMPERSAND
                    // character (&) consist of a sequence of one or more
                    // alphanumeric ASCII characters followed by a U+003B
                    // SEMICOLON character (;), then this is a parse error".

                    tokenizer.discard_char();
                    tokenizer.unconsume(self.name_buf.take_unwrap());
                    self.finish_none(false)
                }
                Some(m) => {
                    // We have a complete match.
                    self.result = Some(CharRef {
                        chars: *m,
                        num_chars: if m[1] == '\0' { 1 } else { 2 },
                        parse_error: self.last_name_char != ';',
                    });
                    Done
                }
            }
        }
    }
}
<commit_msg>Handle failure to extend a previous char ref match<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use super::SubTok;

use std::char::{to_digit, from_u32};

mod data;

pub struct CharRef {
    chars: [char, ..2],
    num_chars: u8,
    parse_error: bool,
}

pub enum Status {
    Stuck,
    Progress,
    Done,
}

enum State {
    Begin,
    Octothorpe,
    Numeric(u32), // base
    NumericSemicolon,
    Named,
}

pub struct CharRefTokenizer {
    priv state: State,
    priv addnl_allowed: Option<char>,
    priv result: Option<CharRef>,

    priv num: u32,
    priv num_too_big: bool,
    priv seen_digit: bool,
    priv hex_marker: Option<char>,

    priv name_buf_opt: Option<~str>,
    priv name_match: Option<&'static [char, ..2]>,
    priv name_len: uint,
}

impl CharRefTokenizer {
    pub fn new(addnl_allowed: Option<char>) -> CharRefTokenizer {
        CharRefTokenizer {
            state: Begin,
            addnl_allowed: addnl_allowed,
            result: None,
            num: 0,
            num_too_big: false,
            seen_digit: false,
            hex_marker: None,
            name_buf_opt: None,
            name_match: None,
            name_len: 0,
        }
    }

    pub fn step<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        if self.result.is_some() {
            return Done;
        }

        match self.state {
            Begin => self.do_begin(tokenizer),
            Octothorpe => self.do_octothorpe(tokenizer),
            Numeric(base) => self.do_numeric(tokenizer, base),
            NumericSemicolon => self.do_numeric_semicolon(tokenizer),
            Named => self.do_named(tokenizer),
        }
    }

    // A CharRefTokenizer can only tokenize one character reference,
    // so this method consumes the tokenizer.
    pub fn get_result(self) -> CharRef {
        self.result.expect("get_result called before done")
    }

    fn name_buf<'t>(&'t mut self) -> &'t mut ~str {
        self.name_buf_opt.as_mut()
            .expect("name_buf missing in named character reference")
    }

    fn finish_none(&mut self, error: bool) -> Status {
        self.result = Some(CharRef {
            chars: ['\0', '\0'],
            num_chars: 0,
            parse_error: error,
        });
        Done
    }

    fn finish_one(&mut self, c: char, error: bool) -> Status {
        self.result = Some(CharRef {
            chars: [c, '\0'],
            num_chars: 1,
            parse_error: error,
        });
        Done
    }

    fn do_begin<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        match unwrap_or_return!(tokenizer.peek(), Stuck) {
            '\t' | '\n' | '\x0C' | ' ' | '<' | '&'
                => self.finish_none(false),
            c if Some(c) == self.addnl_allowed
                => self.finish_none(false),

            '#' => {
                tokenizer.discard_char();
                self.state = Octothorpe;
                Progress
            }

            _ => {
                self.state = Named;
                self.name_buf_opt = Some(~"");
                Progress
            }
        }
    }

    fn do_octothorpe<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        match c {
            'x' | 'X' => {
                tokenizer.discard_char();
                self.hex_marker = Some(c);
                self.state = Numeric(16);
            }

            _ => {
                self.hex_marker = None;
                self.state = Numeric(10);
            }
        }
        Progress
    }

    fn do_numeric<T: SubTok>(&mut self, tokenizer: &mut T, base: u32) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        match to_digit(c, base as uint) {
            Some(n) => {
                tokenizer.discard_char();
                self.num *= base;
                if self.num > 0x10FFFF {
                    // We might overflow, and the character is definitely invalid.
                    // We still parse digits and semicolon, but don't use the result.
                    self.num_too_big = true;
                }
                self.num += n as u32;
                self.seen_digit = true;
                Progress
            }

            None if !self.seen_digit => {
                let mut unconsume = ~"#";
                match self.hex_marker {
                    Some(c) => unconsume.push_char(c),
                    None => (),
                }

                tokenizer.unconsume(unconsume);
                self.finish_none(true)
            }

            None => {
                self.state = NumericSemicolon;
                Progress
            }
        }
    }

    fn do_numeric_semicolon<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        fn conv(n: u32) -> char {
            from_u32(n).expect("invalid char missed by error handling cases")
        }

        let semi_missing = match unwrap_or_return!(tokenizer.peek(), Stuck) {
            ';' => { tokenizer.discard_char(); false }
            _   => true
        };

        match self.num {
            n if (n > 0x10FFFF) || self.num_too_big => self.finish_one('\ufffd', true),
            0x00 | 0xD800..0xDFFF => self.finish_one('\ufffd', true),

            0x80..0x9F => match data::c1_replacements[self.num - 0x80] {
                Some(c) => self.finish_one(c, true),
                None => self.finish_one(conv(self.num), semi_missing),
            },

            0x01..0x08 | 0x0D..0x1F | 0x7F..0x9F | 0xFDD0..0xFDEF | 0x0B
                => self.finish_one(conv(self.num), true),

            n if (n & 0xFFFE) == 0xFFFE
                => self.finish_one(conv(n), true),

            n => self.finish_one(conv(n), semi_missing),
        }
    }

    fn do_named<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        tokenizer.discard_char();
        self.name_buf().push_char(c);
        match data::named_entities.find(&self.name_buf().as_slice()) {
            // We have either a full match or a prefix of one.
            Some(m) => {
                if m[0] != '\0' {
                    // We have a full match, but there might be a longer one to come.
                    self.name_match = Some(m);
                    self.name_len = self.name_buf().len();
                }
                // Otherwise we just have a prefix match.
                Progress
            }

            // Can't continue the match.
            None => match self.name_match {
                None => {
                    // FIXME: "if the characters after the U+0026 AMPERSAND
                    // character (&) consist of a sequence of one or more
                    // alphanumeric ASCII characters followed by a U+003B
                    // SEMICOLON character (;), then this is a parse error".

                    tokenizer.unconsume(self.name_buf_opt.take_unwrap());
                    self.finish_none(false)
                }
                Some(m) => {
                    // We have a complete match, but we've consumed at least
                    // one additional character into self.name_buf, and more
                    // in cases like
                    //
                    //     &not    => match for U+00AC
                    //     &noti   => valid prefix for &notin
                    //     &notit  => can't continue match

                    assert!(self.name_len > 0);
                    assert!(self.name_len < self.name_buf().len());
                    tokenizer.unconsume(self.name_buf().slice_from(self.name_len).to_owned());
                    let missing_semi = ';' != self.name_buf().char_at(self.name_len-1);

                    self.result = Some(CharRef {
                        chars: *m,
                        num_chars: if m[1] == '\0' { 1 } else { 2 },
                        parse_error: missing_semi,
                    });
                    Done
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(type_alias_impl_trait)]

trait T {
    type Item;
}

type Alias<'a> = impl T<Item = &'a ()>;

struct S;
impl<'a> T for &'a S {
    type Item = &'a ();
}

fn filter_positive<'a>() -> Alias<'a> {
    &S
}

fn with_positive(fun: impl Fn(Alias<'_>)) {
    fun(filter_positive());
}

fn main() {
    with_positive(|_| ());
}
<commit_msg>Delete miri test<commit_after><|endoftext|>


<commit_before>use std::fs::{self, File};
use std::io::prelude::*;

use cargotest::support::{project, execs};
use hamcrest::{assert_that, existing_file, is_not};

#[test]
fn adding_and_removing_packages() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            authors = []
            version = "0.0.1"
        "#)
        .file("bar/src/lib.rs", "")
        .build();

    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));

    let toml = p.root().join("Cargo.toml");
    let lock1 = p.read_lockfile();

    // add a dep
    File::create(&toml).unwrap().write_all(br#"
        [package]
        name = "foo"
        authors = []
        version = "0.0.1"

        [dependencies.bar]
        path = "bar"
    "#).unwrap();
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));
    let lock2 = p.read_lockfile();
    assert_ne!(lock1, lock2);

    // change the dep
    File::create(&p.root().join("bar/Cargo.toml")).unwrap().write_all(br#"
        [package]
        name = "bar"
        authors = []
        version = "0.0.2"
    "#).unwrap();
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));
    let lock3 = p.read_lockfile();
    assert_ne!(lock1, lock3);
    assert_ne!(lock2, lock3);

    // remove the dep
    println!("lock4");
    File::create(&toml).unwrap().write_all(br#"
        [package]
        name = "foo"
        authors = []
        version = "0.0.1"
    "#).unwrap();
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));
    let lock4 = p.read_lockfile();
    assert_eq!(lock1, lock4);
}

#[test]
fn no_index_update() {
    use cargotest::ChannelChanger;
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"

            [dependencies]
            serde = "1.0"
        "#)
        .file("src/main.rs", "fn main() {}")
        .build();

    assert_that(p.cargo("generate-lockfile"),
                execs().with_stdout("")
                    .with_stderr_contains("    Updating registry `https://github.com/rust-lang/crates.io-index`"));

    assert_that(p.cargo("generate-lockfile").masquerade_as_nightly_cargo().arg("-Zno-index-update"),
                execs().with_status(0).with_stdout("")
                    .with_stderr_does_not_contain("    Updating registry `https://github.com/rust-lang/crates.io-index`"));
}

#[test]
fn preserve_metadata() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            authors = []
            version = "0.0.1"
        "#)
        .file("bar/src/lib.rs", "")
        .build();

    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));

    let metadata = r#"
[metadata]
bar = "baz"
foo = "bar"
"#;
    let lockfile = p.root().join("Cargo.lock");
    let lock = p.read_lockfile();
    let data = lock + metadata;
    File::create(&lockfile).unwrap().write_all(data.as_bytes()).unwrap();

    // Build and make sure the metadata is still there
    assert_that(p.cargo("build"),
                execs().with_status(0));
    let lock = p.read_lockfile();
    assert!(lock.contains(metadata.trim()), "{}", lock);

    // Update and make sure the metadata is still there
    assert_that(p.cargo("update"),
                execs().with_status(0));
    let lock = p.read_lockfile();
    assert!(lock.contains(metadata.trim()), "{}", lock);
}

#[test]
fn preserve_line_endings_issue_2076() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            authors = []
            version = "0.0.1"
        "#)
        .file("bar/src/lib.rs", "")
        .build();

    let lockfile = p.root().join("Cargo.lock");
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));
    assert_that(&lockfile,
                existing_file());
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));

    let lock0 = p.read_lockfile();

    assert!(lock0.starts_with("[[package]]\n"));

    let lock1 = lock0.replace("\n", "\r\n");
    {
        File::create(&lockfile).unwrap().write_all(lock1.as_bytes()).unwrap();
    }

    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));

    let lock2 = p.read_lockfile();

    assert!(lock2.starts_with("[[package]]\r\n"));
    assert_eq!(lock1, lock2);
}

#[test]
fn cargo_update_generate_lockfile() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .build();

    let lockfile = p.root().join("Cargo.lock");
    assert_that(&lockfile, is_not(existing_file()));
    assert_that(p.cargo("update"), execs().with_status(0).with_stdout(""));
    assert_that(&lockfile, existing_file());

    fs::remove_file(p.root().join("Cargo.lock")).unwrap();

    assert_that(&lockfile, is_not(existing_file()));
    assert_that(p.cargo("update"), execs().with_status(0).with_stdout(""));
    assert_that(&lockfile, existing_file());

}
<commit_msg>Update a test to not clone the real index<commit_after>use std::fs::{self, File};
use std::io::prelude::*;

use cargotest::support::{project, execs};
use cargotest::support::registry::Package;
use cargotest::ChannelChanger;
use hamcrest::{assert_that, existing_file, is_not};

#[test]
fn adding_and_removing_packages() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            authors = []
            version = "0.0.1"
        "#)
        .file("bar/src/lib.rs", "")
        .build();

    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));

    let toml = p.root().join("Cargo.toml");
    let lock1 = p.read_lockfile();

    // add a dep
    File::create(&toml).unwrap().write_all(br#"
        [package]
        name = "foo"
        authors = []
        version = "0.0.1"

        [dependencies.bar]
        path = "bar"
    "#).unwrap();
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));
    let lock2 = p.read_lockfile();
    assert_ne!(lock1, lock2);

    // change the dep
    File::create(&p.root().join("bar/Cargo.toml")).unwrap().write_all(br#"
        [package]
        name = "bar"
        authors = []
        version = "0.0.2"
    "#).unwrap();
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));
    let lock3 = p.read_lockfile();
    assert_ne!(lock1, lock3);
    assert_ne!(lock2, lock3);

    // remove the dep
    println!("lock4");
    File::create(&toml).unwrap().write_all(br#"
        [package]
        name = "foo"
        authors = []
        version = "0.0.1"
    "#).unwrap();
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));
    let lock4 = p.read_lockfile();
    assert_eq!(lock1, lock4);
}

#[test]
fn no_index_update() {
    Package::new("serde", "1.0.0").publish();

    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"

            [dependencies]
            serde = "1.0"
        "#)
        .file("src/main.rs", "fn main() {}")
        .build();

    assert_that(p.cargo("generate-lockfile"),
                execs().with_stderr("\
[UPDATING] registry `[..]`
"));

    assert_that(p.cargo("generate-lockfile").masquerade_as_nightly_cargo().arg("-Zno-index-update"),
                execs().with_status(0).with_stdout("").with_stderr(""));
}

#[test]
fn preserve_metadata() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            authors = []
            version = "0.0.1"
        "#)
        .file("bar/src/lib.rs", "")
        .build();

    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));

    let metadata = r#"
[metadata]
bar = "baz"
foo = "bar"
"#;
    let lockfile = p.root().join("Cargo.lock");
    let lock = p.read_lockfile();
    let data = lock + metadata;
    File::create(&lockfile).unwrap().write_all(data.as_bytes()).unwrap();

    // Build and make sure the metadata is still there
    assert_that(p.cargo("build"),
                execs().with_status(0));
    let lock = p.read_lockfile();
    assert!(lock.contains(metadata.trim()), "{}", lock);

    // Update and make sure the metadata is still there
    assert_that(p.cargo("update"),
                execs().with_status(0));
    let lock = p.read_lockfile();
    assert!(lock.contains(metadata.trim()), "{}", lock);
}

#[test]
fn preserve_line_endings_issue_2076() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            authors = []
            version = "0.0.1"
        "#)
        .file("bar/src/lib.rs", "")
        .build();

    let lockfile = p.root().join("Cargo.lock");
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));
    assert_that(&lockfile,
                existing_file());
    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));

    let lock0 = p.read_lockfile();

    assert!(lock0.starts_with("[[package]]\n"));

    let lock1 = lock0.replace("\n", "\r\n");
    {
        File::create(&lockfile).unwrap().write_all(lock1.as_bytes()).unwrap();
    }

    assert_that(p.cargo("generate-lockfile"),
                execs().with_status(0));

    let lock2 = p.read_lockfile();

    assert!(lock2.starts_with("[[package]]\r\n"));
    assert_eq!(lock1, lock2);
}

#[test]
fn cargo_update_generate_lockfile() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            authors = []
            version = "0.0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .build();

    let lockfile = p.root().join("Cargo.lock");
    assert_that(&lockfile, is_not(existing_file()));
    assert_that(p.cargo("update"), execs().with_status(0).with_stdout(""));
    assert_that(&lockfile, existing_file());

    fs::remove_file(p.root().join("Cargo.lock")).unwrap();

    assert_that(&lockfile, is_not(existing_file()));
    assert_that(p.cargo("update"), execs().with_status(0).with_stdout(""));
    assert_that(&lockfile, existing_file());

}
<|endoftext|>


<commit_before><commit_msg>05 - casting<commit_after><|endoftext|>


<commit_before>#![feature(test)]
extern crate test;

extern crate onmf;

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

extern crate num;
use num::{Float};

extern crate ndarray;
use ndarray::{ArrayBase};

// TODO make a macro that creates these benches

macro_rules! bench_ortho_nmf {
    ($bencher:expr, $float:ty, $nhidden:expr, $nobserved:expr, $nsamples:expr) => {{
        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        let mut ortho_nmf = onmf::OrthogonalNMF::<$float>::init_random01(
            $nhidden, $nobserved, $nsamples, &mut rng);

        let samples = DMat::<$float>::new_ones($nsamples, $nobserved);

        let alpha: $float = 0.1 * 1.01.powi(0);
        $bencher.iter(|| {
            ortho_nmf.iterate(alpha, &samples);
        });
    }}
}

macro_rules! bench_ortho_nmf_blas {
    ($bencher:expr, $nhidden:expr, $nobserved:expr, $nsamples:expr) => {{
        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        let mut ortho_nmf = onmf::OrthogonalNMFBlas::new_random01(
            $nhidden, $nobserved, $nsamples, &mut rng);

        let mut samples = ArrayBase::<Vec<f32>, (usize, usize)>::from_elem(($nsamples, $nobserved), 1.);

        let alpha: f32 = 0.1 * 1.01.powi(0);
        $bencher.iter(|| {
            ortho_nmf.iterate(alpha, &mut samples);
        });
    }}
}

#[bench]
fn bench_ortho_nmf_blas_8_32_16(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 8, 32, 16);
}

#[bench]
fn bench_ortho_nmf_blas_6_32_206(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 6, 32, 206);
}

#[bench]
fn bench_ortho_nmf_blas_10_64_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 64, 30);
}
#[bench]
fn bench_ortho_nmf_blas_10_64_60(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 64, 60);
}

#[bench]
fn bench_ortho_nmf_blas_10_64_100(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 64, 100);
}

#[bench]
fn bench_ortho_nmf_f64_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 11);
}
#[bench]
fn bench_ortho_nmf_f32_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 11);
}
#[bench]
fn bench_ortho_nmf_blas_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 256, 11);
}

#[bench]
fn bench_ortho_nmf_f64_10_256_20(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 20);
}
#[bench]
fn bench_ortho_nmf_f32_10_256_20(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 20);
}
#[bench]
fn bench_ortho_nmf_blas_10_256_20(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 256, 20);
}

#[bench]
fn bench_ortho_nmf_f64_10_256_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 30);
}
#[bench]
fn bench_ortho_nmf_f32_10_256_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 30);
}
#[bench]
fn bench_ortho_nmf_blas_10_256_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 256, 30);
}

#[bench]
fn bench_ortho_nmf_f64_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 512, 11);
}
#[bench]
fn bench_ortho_nmf_f32_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 512, 11);
}
#[bench]
fn bench_ortho_nmf_blas_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 512, 11);
}

#[bench]
fn bench_ortho_nmf_f64_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 20, 512, 30);
}
#[bench]
fn bench_ortho_nmf_f32_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 20, 512, 30);
}
#[bench]
fn bench_ortho_nmf_blas_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 20, 512, 30);
}
<commit_msg>make some benches run again after changes to nmf<commit_after>#![feature(test)]
extern crate test;

extern crate onmf;

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

extern crate num;
use num::{Float};

extern crate ndarray;
use ndarray::{ArrayBase};

// TODO make a macro that creates these benches

macro_rules! bench_ortho_nmf {
    ($bencher:expr, $float:ty, $nhidden:expr, $nobserved:expr, $nsamples:expr) => {{
        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        let mut ortho_nmf = onmf::OrthogonalNMF::<$float>::init_random01(
            $nhidden, $nobserved, $nsamples, &mut rng);

        let samples = DMat::<$float>::new_ones($nsamples, $nobserved);

        let alpha: $float = 0.1 * 1.01.powi(0);
        $bencher.iter(|| {
            ortho_nmf.iterate(alpha, &samples);
        });
    }}
}

macro_rules! bench_ortho_nmf_blas {
    ($bencher:expr, $nhidden:expr, $nobserved:expr, $nsamples:expr) => {{
        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        let mut ortho_nmf = onmf::NMFBlas::new_random01(
            $nhidden, $nobserved, $nsamples, &mut rng);

        let mut samples = ArrayBase::<Vec<f32>, (usize, usize)>::from_elem(($nsamples, $nobserved), 1.);

        // let alpha: Option<$float> = Some(0.1 * 1.01.powi(0));
        let alpha: Option<f32> = None;
        $bencher.iter(|| {
            ortho_nmf.iterate(&mut samples, alpha);
        });
    }}
}

#[bench]
fn bench_ortho_nmf_blas_4_32_5(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 4, 32, 5);
}

#[bench]
fn bench_ortho_nmf_blas_4_32_7(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 4, 32, 7);
}

#[bench]
fn bench_ortho_nmf_blas_8_32_16(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 8, 32, 16);
}

#[bench]
fn bench_ortho_nmf_blas_6_32_206(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 6, 32, 206);
}

#[bench]
fn bench_ortho_nmf_blas_10_64_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 64, 30);
}
#[bench]
fn bench_ortho_nmf_blas_10_64_60(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 64, 60);
}

#[bench]
fn bench_ortho_nmf_blas_10_64_100(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 64, 100);
}

#[bench]
fn bench_ortho_nmf_f64_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 11);
}
#[bench]
fn bench_ortho_nmf_f32_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 11);
}
#[bench]
fn bench_ortho_nmf_blas_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 256, 11);
}

#[bench]
fn bench_ortho_nmf_f64_10_256_20(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 20);
}
#[bench]
fn bench_ortho_nmf_f32_10_256_20(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 20);
}
#[bench]
fn bench_ortho_nmf_blas_10_256_20(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 256, 20);
}

#[bench]
fn bench_ortho_nmf_f64_10_256_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 30);
}
#[bench]
fn bench_ortho_nmf_f32_10_256_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 30);
}
#[bench]
fn bench_ortho_nmf_blas_10_256_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 256, 30);
}

#[bench]
fn bench_ortho_nmf_f64_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 512, 11);
}
#[bench]
fn bench_ortho_nmf_f32_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 512, 11);
}
#[bench]
fn bench_ortho_nmf_blas_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 10, 512, 11);
}

#[bench]
fn bench_ortho_nmf_f64_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 20, 512, 30);
}
#[bench]
fn bench_ortho_nmf_f32_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 20, 512, 30);
}
#[bench]
fn bench_ortho_nmf_blas_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf_blas!(bencher, 20, 512, 30);
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

//! # pest. The Elegant Parser
//!
//! pest is a [PEG](https://en.wikipedia.org/wiki/Parsing_expression_grammar) parser built with
//! *simplicity* and *speed* in mind.
//!
//! ## Parser
//!
//! pest works mainly through a `trait`, `Parser`, which provides an interface to the parsing
//! functionality. Since `Parser` is a `trait`, parsing needs to be defined either though the
//! `#[derive(Parser)]` attribute, or manually through the [`Position API`](struct.Position.html).
//! The use of the //! `derive` is highly encouraged since this is the only way you can make
//! use of pest's PEG grammar, while manual parser definition can be used where highly specific
//! or efficient parsing is required.
//!
//! ## `#[derive(Parser)]`
//!
//! pest comes with a procedural macro crate--`pest_derive`--which needs to be included in
//! `Cargo.toml` in order to enable the `derive`.
//!
//! ```toml
//! pest_derive = "*"
//! ```
//!
//! ## `.pest` files
//!
//! Grammar definitions reside in custom `.pest` files located in the `src` directory. Their path is
//! relative to `src` and is specified between the `derive` attribute and an empty `struct` that
//! `Parser` will be derived on.
//!
//! Because of a limitation in procedural macros, there is no way for Cargo to know that a module
//! needs to be recompiled based on the file that the procedural macro is opening. This leads to the
//! case where modifying a `.pest` file without touching the file where the `derive` is does not
//! recompile it if it already has a working binary in the cache. To avoid this issue, the grammar
//! file can be included in a dummy `const` definition while debugging.
//!
//! ```ignore
//! #[cfg(debug_assertions)]
//! const _GRAMMAR: &'static str = include_str!("path/to/my_grammar.pest"); // relative to this file
//!
//! #[derive(Parser)]
//! #[grammar = "path/to/my_grammar.pest"] // relative to src
//! struct MyParser;
//! ```
//!
//! The grammar of `.pest` files is documented in the
//! [`pest_derive` crate](https://docs.rs/pest_derive/#Grammar).

#![doc(html_root_url = "https://docs.rs/pest")]

use std::fmt::Debug;
use std::hash::Hash;

mod error;
pub mod iterators;
mod macros;
mod parser;
mod parser_state;
mod position;
pub mod prec_climber;
mod span;
mod token;

/// A `trait` which parser rules must implement.
///
/// This trait is set up so that any struct that implements all of its required traits will
/// automatically implement this trait as well.
///
/// This is essentially a [trait alias](https://github.com/rust-lang/rfcs/pull/1733). When trait
/// aliases are implemented, this may be replaced by one.
pub trait RuleType: Copy + Debug + Eq + Hash + Ord {}
impl<T: Copy + Debug + Eq + Hash + Ord> RuleType for T {}

pub use error::Error;
pub use parser::Parser;
pub use parser_state::{state, Atomicity, Lookahead, ParserState};
pub use position::Position;
pub use span::Span;
pub use token::Token;
<commit_msg>Fixed documentation.<commit_after>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

//! # pest. The Elegant Parser
//!
//! pest is a [PEG](https://en.wikipedia.org/wiki/Parsing_expression_grammar) parser built with
//! *simplicity* and *speed* in mind.
//!
//! ## Parser
//!
//! pest works mainly through a `trait`, `Parser`, which provides an interface to the parsing
//! functionality. Since `Parser` is a `trait`, parsing needs to be defined either though the
//! `#[derive(Parser)]` attribute, or manually through the [`Position API`](struct.Position.html).
//! The use of the `derive` is highly encouraged since this is the only way you can make use of
//! pest's PEG grammar, while manual parser definition can be used where highly specific or
//! efficient parsing is required.
//!
//! ## `#[derive(Parser)]`
//!
//! pest comes with a procedural macro crate--`pest_derive`--which needs to be included in
//! `Cargo.toml` in order to enable the `derive`.
//!
//! ```toml
//! pest_derive = "*"
//! ```
//!
//! ## `.pest` files
//!
//! Grammar definitions reside in custom `.pest` files located in the `src` directory. Their path is
//! relative to `src` and is specified between the `derive` attribute and an empty `struct` that
//! `Parser` will be derived on.
//!
//! Because of a limitation in procedural macros, there is no way for Cargo to know that a module
//! needs to be recompiled based on the file that the procedural macro is opening. This leads to the
//! case where modifying a `.pest` file without touching the file where the `derive` is does not
//! recompile it if it already has a working binary in the cache. To avoid this issue, the grammar
//! file can be included in a dummy `const` definition while debugging.
//!
//! ```ignore
//! #[cfg(debug_assertions)]
//! const _GRAMMAR: &'static str = include_str!("path/to/my_grammar.pest"); // relative to this file
//!
//! #[derive(Parser)]
//! #[grammar = "path/to/my_grammar.pest"] // relative to src
//! struct MyParser;
//! ```
//!
//! The grammar of `.pest` files is documented in the
//! [`pest_derive` crate](https://docs.rs/pest_derive/#Grammar).

#![doc(html_root_url = "https://docs.rs/pest")]

use std::fmt::Debug;
use std::hash::Hash;

mod error;
pub mod iterators;
mod macros;
mod parser;
mod parser_state;
mod position;
pub mod prec_climber;
mod span;
mod token;

/// A `trait` which parser rules must implement.
///
/// This trait is set up so that any struct that implements all of its required traits will
/// automatically implement this trait as well.
///
/// This is essentially a [trait alias](https://github.com/rust-lang/rfcs/pull/1733). When trait
/// aliases are implemented, this may be replaced by one.
pub trait RuleType: Copy + Debug + Eq + Hash + Ord {}
impl<T: Copy + Debug + Eq + Hash + Ord> RuleType for T {}

pub use error::Error;
pub use parser::Parser;
pub use parser_state::{state, Atomicity, Lookahead, ParserState};
pub use position::Position;
pub use span::Span;
pub use token::Token;
<|endoftext|>


<commit_before>// Copyright 2017 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.

// compile-flags: -C no-prepopulate-passes

// This test that using union forward the abi of the inner type, as
// discussed in #54668

#![crate_type="lib"]
#![feature(repr_simd)]

#[derive(Copy, Clone)]
pub enum Unhab {}

#[repr(simd)]
#[derive(Copy, Clone)]
pub struct i64x4(i64, i64, i64, i64);

#[derive(Copy, Clone)]
pub union UnionI64x4{ a:(), b: i64x4 }

// CHECK: define <4 x i64> @test_UnionI64x4(<4 x i64> %arg0)
#[no_mangle]
pub extern fn test_UnionI64x4(_: UnionI64x4) -> UnionI64x4 { loop {} }

pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 }

// CHECK: define <4 x i64> @test_UnionI64x4_(<4 x i64> %arg0)
#[no_mangle]
pub extern fn test_UnionI64x4_(_: UnionI64x4_) -> UnionI64x4_ { loop {} }

pub union UnionI64x4I64{ a: i64x4, b: i64 }

// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %arg0)
#[no_mangle]
pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} }

pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) }

// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %arg0)
#[no_mangle]
pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} }

pub union UnionF32{a:f32}

// CHECK: define float @test_UnionF32(float %arg0)
#[no_mangle]
pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }

pub union UnionF32F32{a:f32, b:f32}

// CHECK: define float @test_UnionF32F32(float %arg0)
#[no_mangle]
pub extern fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} }

pub union UnionF32U32{a:f32, b:u32}

// CHECK: define i32 @test_UnionF32U32(i32)
#[no_mangle]
pub extern fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }

pub union UnionU128{a:u128}
// CHECK: define i128 @test_UnionU128(i128 %arg0)
#[no_mangle]
pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} }

#[repr(C)]
pub union CUnionU128{a:u128}
// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %arg0)
#[no_mangle]
pub fn test_CUnionU128(_: CUnionU128) { loop {} }

<commit_msg>Remove extern and some return value as an attempt to make the test pass on more platforms<commit_after>// Copyright 2017 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.

// compile-flags: -C no-prepopulate-passes

// This test that using union forward the abi of the inner type, as
// discussed in #54668

#![crate_type="lib"]
#![feature(repr_simd)]

#[derive(Copy, Clone)]
pub enum Unhab {}

#[repr(simd)]
#[derive(Copy, Clone)]
pub struct i64x4(i64, i64, i64, i64);

#[derive(Copy, Clone)]
pub union UnionI64x4{ a:(), b: i64x4 }

// CHECK: define void @test_UnionI64x4(<4 x i64>* {{.*}} %arg0)
#[no_mangle]
pub fn test_UnionI64x4(_: UnionI64x4) { loop {} }

pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 }

// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %arg0)
#[no_mangle]
pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} }

pub union UnionI64x4I64{ a: i64x4, b: i64 }

// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %arg0)
#[no_mangle]
pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} }

pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) }

// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %arg0)
#[no_mangle]
pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} }

pub union UnionF32{a:f32}

// CHECK: define float @test_UnionF32(float %arg0)
#[no_mangle]
pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }

pub union UnionF32F32{a:f32, b:f32}

// CHECK: define float @test_UnionF32F32(float %arg0)
#[no_mangle]
pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} }

pub union UnionF32U32{a:f32, b:u32}

// CHECK: define i32 @test_UnionF32U32(i32)
#[no_mangle]
pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }

pub union UnionU128{a:u128}
// CHECK: define i128 @test_UnionU128(i128 %arg0)
#[no_mangle]
pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} }

#[repr(C)]
pub union CUnionU128{a:u128}
// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %arg0)
#[no_mangle]
pub fn test_CUnionU128(_: CUnionU128) { loop {} }

<|endoftext|>


<commit_before>//! Insertion sort algorithm.
//!
//! The `insertion_sort` module contains the simple sorting algorithm "Insertion Sort".
//!
//! Source: https://en.wikipedia.org/wiki/Insertion_sort

use std::fmt::Debug;

/// Simple sort: insertion sort.
///
/// # Details
///
/// Insertion sort is one of the simplest sorting algorithm. Every elements of the list to sort
/// are picked one at a time and inserted into a the sorted list at the right location.
///
/// In the best case scenario, the list is already sorted and the work is simply to append the
/// element at the end of the list, hence a O(N) scaling.
///
/// In the worst case scenario, the list is in reverse order. Hence, every element is compared to
/// all previous elements already sorted until this new one gets inserted at the beginning of the
/// sorted list, thus making this case O(N^2).
///
/// Insertion sort is still useful as its simplicity (and thus small overhead) makes it ideal for
/// small vectors.
///
/// This function takes an immutable reference vector of any type and returns a vector of `usize`
/// of the same length containing the indices of the initial vector sorted.
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// assert_eq!(vec![3, 1, 2, 0], sorting::simplesorts::insertion::sort(&data));
/// ```
///
pub fn sort<T: Debug + PartialOrd>(input: &Vec<T>) -> Vec<usize> {
    let n = input.len();

    let mut output_index: Vec<usize> = Vec::with_capacity(n);

    // Place the first element's index (0) as the first element of the output_index vector.
    output_index.push(0);

    println!("n = {:?}", n);
    println!("input:        {:?}", input);
    println!("output_index: {:?}", output_index);

    if n > 1 {
        // Loop over input vector, skipping the first element as it's already inserted as the first
        // element of output_index.
        for (i_start_at_0,elem) in input.iter().skip(1).enumerate() {
            let i = i_start_at_0 + 1;
            println!("  i={:?} Finding where to put element {:?} (i={:?}) in output_index: {:?}", i, elem, i, output_index);

            // Verify next element if it is smaller
            // If next element is larger than the last stored index, just place that element at
            // the end.
            if *elem >= input[*output_index.last().unwrap()] {
                // Next element "elem" is already larger than the previous stored index.
                // Just use its index.
                output_index.push(i);

                println!("    1. Pushing element '{:?}' at the end.", elem);
            } else {
                println!("    2. elem ?< input[output_index[0]]");
                println!("           {:?} ?< {:?}", elem, input[output_index[0]]);
                // The next element of the input vector is smaller than the last stored on.
                // Let's find where it should go by looping back on the stored indices.
                // NOTE: we must use a loop on indices as to prevent problems with the borrow-checker.
                if *elem < input[output_index[0]] {
                    println!("        2a. Yes: --> putting i in front");
                    output_index.insert(0, i);
                } else {
                    println!("        2b. No: --> Looping back");
                    for j in (0..i).rev() {
                        println!("            j={:?}   elem={:?}   input[output_index[j]]={:?}", j, elem, input[output_index[j]]);
                        if *elem > input[output_index[j]] {
                            output_index.insert(j+1, i);
                            break;
                        }
                    }
                }
                println!("        3. output_index: {:?}", output_index);
            }

            print!("           output: [");
            for j in output_index.iter() {
                    print!("{:?}, ", input[*j]);
            }
            println!("]");
        }
    }

    println!("");
    println!("END: input:        {:?}", input);
    println!("END: output_index: {:?}", output_index);
    print!("END: output:       [");
    for j in output_index.iter() {
            print!("{:?}, ", input[*j]);
    }
    println!("]");

    assert_eq!(output_index.len(), n);

    return output_index;
}
<commit_msg>Move saline info into own section.<commit_after>//! Insertion sort algorithm.
//!
//! The `insertion_sort` module contains the simple sorting algorithm "Insertion Sort".
//!
//! Source: https://en.wikipedia.org/wiki/Insertion_sort

use std::fmt::Debug;

/// Simple sort: insertion sort.
///
/// # Details
///
/// Insertion sort is one of the simplest sorting algorithm. Every elements of the list to sort
/// are picked one at a time and inserted into a the sorted list at the right location.
///
/// This function takes an immutable reference vector of any type and returns a vector of `usize`
/// of the same length containing the indices of the initial vector sorted.
///
/// # Scaling
///
/// In the best case scenario, the list is already sorted and the work is simply to append the
/// element at the end of the list, hence a O(N) scaling.
///
/// In the worst case scenario, the list is in reverse order. Hence, every element is compared to
/// all previous elements already sorted until this new one gets inserted at the beginning of the
/// sorted list, thus making this case O(N^2).
///
/// Insertion sort is still useful as its simplicity (and thus small overhead) makes it ideal for
/// small vectors.
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// assert_eq!(vec![3, 1, 2, 0], sorting::simplesorts::insertion::sort(&data));
/// ```
///
pub fn sort<T: Debug + PartialOrd>(input: &Vec<T>) -> Vec<usize> {
    let n = input.len();

    let mut output_index: Vec<usize> = Vec::with_capacity(n);

    // Place the first element's index (0) as the first element of the output_index vector.
    output_index.push(0);

    println!("n = {:?}", n);
    println!("input:        {:?}", input);
    println!("output_index: {:?}", output_index);

    if n > 1 {
        // Loop over input vector, skipping the first element as it's already inserted as the first
        // element of output_index.
        for (i_start_at_0,elem) in input.iter().skip(1).enumerate() {
            let i = i_start_at_0 + 1;
            println!("  i={:?} Finding where to put element {:?} (i={:?}) in output_index: {:?}", i, elem, i, output_index);

            // Verify next element if it is smaller
            // If next element is larger than the last stored index, just place that element at
            // the end.
            if *elem >= input[*output_index.last().unwrap()] {
                // Next element "elem" is already larger than the previous stored index.
                // Just use its index.
                output_index.push(i);

                println!("    1. Pushing element '{:?}' at the end.", elem);
            } else {
                println!("    2. elem ?< input[output_index[0]]");
                println!("           {:?} ?< {:?}", elem, input[output_index[0]]);
                // The next element of the input vector is smaller than the last stored on.
                // Let's find where it should go by looping back on the stored indices.
                // NOTE: we must use a loop on indices as to prevent problems with the borrow-checker.
                if *elem < input[output_index[0]] {
                    println!("        2a. Yes: --> putting i in front");
                    output_index.insert(0, i);
                } else {
                    println!("        2b. No: --> Looping back");
                    for j in (0..i).rev() {
                        println!("            j={:?}   elem={:?}   input[output_index[j]]={:?}", j, elem, input[output_index[j]]);
                        if *elem > input[output_index[j]] {
                            output_index.insert(j+1, i);
                            break;
                        }
                    }
                }
                println!("        3. output_index: {:?}", output_index);
            }

            print!("           output: [");
            for j in output_index.iter() {
                    print!("{:?}, ", input[*j]);
            }
            println!("]");
        }
    }

    println!("");
    println!("END: input:        {:?}", input);
    println!("END: output_index: {:?}", output_index);
    print!("END: output:       [");
    for j in output_index.iter() {
            print!("{:?}, ", input[*j]);
    }
    println!("]");

    assert_eq!(output_index.len(), n);

    return output_index;
}
<|endoftext|>


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

use command_line::command_line_init;
use interfaces::cef_app_t;
use types::{cef_main_args_t, cef_settings_t};

use geom::size::TypedSize2D;
use libc::{c_char, c_int, c_void};
use util::opts;
use std::borrow::ToOwned;
use std::ffi;
use std::str;
use browser;

const MAX_RENDERING_THREADS: uint = 128;

// TODO(pcwalton): Get the home page via the CEF API.
static HOME_URL: &'static str = "http://s27.postimg.org/vqbtrolyr/servo.jpg";

static CEF_API_HASH_UNIVERSAL: &'static [u8] = b"8efd129f4afc344bd04b2feb7f73a149b6c4e27f\0";
#[cfg(target_os="windows")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"5c7f3e50ff5265985d11dc1a466513e25748bedd\0";
#[cfg(target_os="macos")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"6813214accbf2ebfb6bdcf8d00654650b251bf3d\0";
#[cfg(target_os="linux")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"2bc564c3871965ef3a2531b528bda3e17fa17a6d\0";

#[cfg(target_os="linux")]
fn resources_path() -> Option<String> {
    Some("../../servo/resources".to_owned())
}

#[cfg(not(target_os="linux"))]
fn resources_path() -> Option<String> {
    None
}

#[no_mangle]
pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
                                 settings: *mut cef_settings_t,
                                 application: *mut cef_app_t,
                                 _windows_sandbox_info: *const c_void)
                                 -> c_int {
    if args.is_null() {
        return 0;
    }

    unsafe {
        command_line_init((*args).argc, (*args).argv);

        if !application.is_null() {
            (*application).get_browser_process_handler.map(|cb| {
                    let handler = cb(application);
                    if !handler.is_null() {
                        (*handler).on_context_initialized.map(|hcb| hcb(handler));
                    }
            });
        }
    }

    let rendering_threads = unsafe {
        if ((*settings).rendering_threads as uint) < 1 {
            1
        } else if (*settings).rendering_threads as uint > MAX_RENDERING_THREADS {
            MAX_RENDERING_THREADS
        } else {
            (*settings).rendering_threads as uint
        }
    };

    let urls = vec![HOME_URL.to_owned()];
    opts::set_opts(opts::Opts {
        urls: urls,
        paint_threads: rendering_threads,
        gpu_painting: false,
        tile_size: 512,
        device_pixels_per_px: None,
        time_profiler_period: None,
        memory_profiler_period: None,
        enable_experimental: false,
        nonincremental_layout: false,
        layout_threads: rendering_threads,
        output_file: None,
        headless: false,
        hard_fail: false,
        bubble_inline_sizes_separately: false,
        show_debug_borders: false,
        show_debug_fragment_borders: false,
        show_debug_parallel_paint: false,
        show_debug_parallel_layout: false,
        enable_text_antialiasing: true,
        trace_layout: false,
        devtools_port: None,
        initial_window_size: TypedSize2D(800, 600),
        profile_tasks: false,
        user_agent: None,
        dump_flow_tree: false,
        validate_display_list_geometry: false,
        resources_path: resources_path(),
    });

    return 1
}

#[no_mangle]
pub extern "C" fn cef_shutdown() {
}

#[no_mangle]
pub extern "C" fn cef_run_message_loop() {
    // GWTODO: Support blocking message loop
    // again. Although, will it ever actually
    // be used or will everything use the
    // cef_do_message_loop_work function below
    // as our current miniservo apps do?
    unimplemented!()
}

#[no_mangle]
pub extern "C" fn cef_do_message_loop_work() {
    browser::update();
}

#[no_mangle]
pub extern "C" fn cef_quit_message_loop() {
}

#[no_mangle]
pub extern "C" fn cef_execute_process(_args: *const cef_main_args_t,
                                      _app: *mut cef_app_t,
                                      _windows_sandbox_info: *mut c_void)
                                      -> c_int {
   -1
}

#[no_mangle]
pub extern "C" fn cef_api_hash(entry: c_int) -> *const c_char {
    if entry == 0 {
        &CEF_API_HASH_PLATFORM[0] as *const u8 as *const c_char
    } else {
        &CEF_API_HASH_UNIVERSAL[0] as *const u8 as *const c_char
    }
}

#[no_mangle]
pub extern "C" fn cef_log(_file: *const c_char,
                          _line: c_int,
                          _severity: c_int,
                          message: *const c_char) {
    unsafe {
        let slice = ffi::c_str_to_bytes(&message);
        println!("{}", str::from_utf8(slice).unwrap())
    }
}

#[no_mangle]
pub extern "C" fn cef_get_min_log_level() -> c_int {
    0
}

<commit_msg>using opts::default_opts() in cef/core.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use command_line::command_line_init;
use interfaces::cef_app_t;
use types::{cef_main_args_t, cef_settings_t};

use geom::size::TypedSize2D;
use libc::{c_char, c_int, c_void};
use util::opts;
use std::borrow::ToOwned;
use std::ffi;
use std::str;
use browser;

const MAX_RENDERING_THREADS: uint = 128;

// TODO(pcwalton): Get the home page via the CEF API.
static HOME_URL: &'static str = "http://s27.postimg.org/vqbtrolyr/servo.jpg";

static CEF_API_HASH_UNIVERSAL: &'static [u8] = b"8efd129f4afc344bd04b2feb7f73a149b6c4e27f\0";
#[cfg(target_os="windows")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"5c7f3e50ff5265985d11dc1a466513e25748bedd\0";
#[cfg(target_os="macos")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"6813214accbf2ebfb6bdcf8d00654650b251bf3d\0";
#[cfg(target_os="linux")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"2bc564c3871965ef3a2531b528bda3e17fa17a6d\0";

#[cfg(target_os="linux")]
fn resources_path() -> Option<String> {
    Some("../../servo/resources".to_owned())
}

#[cfg(not(target_os="linux"))]
fn resources_path() -> Option<String> {
    None
}

#[no_mangle]
pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
                                 settings: *mut cef_settings_t,
                                 application: *mut cef_app_t,
                                 _windows_sandbox_info: *const c_void)
                                 -> c_int {
    if args.is_null() {
        return 0;
    }

    unsafe {
        command_line_init((*args).argc, (*args).argv);

        if !application.is_null() {
            (*application).get_browser_process_handler.map(|cb| {
                    let handler = cb(application);
                    if !handler.is_null() {
                        (*handler).on_context_initialized.map(|hcb| hcb(handler));
                    }
            });
        }
    }

    let rendering_threads = unsafe {
        if ((*settings).rendering_threads as uint) < 1 {
            1
        } else if (*settings).rendering_threads as uint > MAX_RENDERING_THREADS {
            MAX_RENDERING_THREADS
        } else {
            (*settings).rendering_threads as uint
        }
    };

    let urls = vec![HOME_URL.to_owned()];
    let mut temp_opts = opts::default_opts();

    temp_opts.paint_threads = rendering_threads;
    temp_opts.layout_threads = rendering_threads;
    temp_opts.headless = false;
    temp_opts.hard_fail = false;
    temp_opts.enable_text_antialiasing = true;
    temp_opts.resources_path = resources_path();
    opts::set_opts(temp_opts);

    return 1
}

#[no_mangle]
pub extern "C" fn cef_shutdown() {
}

#[no_mangle]
pub extern "C" fn cef_run_message_loop() {
    // GWTODO: Support blocking message loop
    // again. Although, will it ever actually
    // be used or will everything use the
    // cef_do_message_loop_work function below
    // as our current miniservo apps do?
    unimplemented!()
}

#[no_mangle]
pub extern "C" fn cef_do_message_loop_work() {
    browser::update();
}

#[no_mangle]
pub extern "C" fn cef_quit_message_loop() {
}

#[no_mangle]
pub extern "C" fn cef_execute_process(_args: *const cef_main_args_t,
                                      _app: *mut cef_app_t,
                                      _windows_sandbox_info: *mut c_void)
                                      -> c_int {
   -1
}

#[no_mangle]
pub extern "C" fn cef_api_hash(entry: c_int) -> *const c_char {
    if entry == 0 {
        &CEF_API_HASH_PLATFORM[0] as *const u8 as *const c_char
    } else {
        &CEF_API_HASH_UNIVERSAL[0] as *const u8 as *const c_char
    }
}

#[no_mangle]
pub extern "C" fn cef_log(_file: *const c_char,
                          _line: c_int,
                          _severity: c_int,
                          message: *const c_char) {
    unsafe {
        let slice = ffi::c_str_to_bytes(&message);
        println!("{}", str::from_utf8(slice).unwrap())
    }
}

#[no_mangle]
pub extern "C" fn cef_get_min_log_level() -> c_int {
    0
}

<|endoftext|>