<commit_before>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(stutter))]

use mem;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let mut r = mem::uninitialized::<CpuidResult>();
    if cfg!(target_arch = "x86") {
        asm!("cpuid"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    } else {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    r
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline(never)]
pub fn has_cpuid() -> bool {
    #[cfg(target_arch = "x86_64")]
    {
        true
    }
    #[cfg(target_arch = "x86")]
    {
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            let _temp: u32;
            unsafe {
                asm!(r#"
                    # Read eflags into $0 and copy into $1:
                    pushfd
                    pop     $0
                    mov     $1, $0
                    # Flip 21st bit:
                    xor     $0, 0x200000
                    # Set eflags:
                    push    $0
                    popfd
                    # Read eflags again, if cpuid is available
                    # the 21st bit will be flipped, otherwise it
                    # it will have the same value as the original in $1:
                    pushfd
                    pop     $0
                    # Xor'ing with the original eflags should have the
                    # 21st bit set to true if cpuid is available and zero
                    # otherwise. All other bits have not been modified and
                    # are zero:
                    xor     $0, $1
                    # Store in $0 the value of the 21st bit
                    shr     $0, 21
                    "#
                     : "=r"(result), "=r"(_temp)
                     :
                     : "cc", "memory"
                     : "intel");
            }
            result != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

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

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<commit_msg>remove unnecessary shift<commit_after>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(stutter))]

use mem;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let mut r = mem::uninitialized::<CpuidResult>();
    if cfg!(target_arch = "x86") {
        asm!("cpuid"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    } else {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    r
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_arch = "x86_64")]
    {
        true
    }
    #[cfg(target_arch = "x86")]
    {
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            let _temp: u32;
            unsafe {
                asm!(r#"
                    # Read eflags into $0 and copy into $1:
                    pushfd
                    pop     $0
                    mov     $1, $0
                    # Flip 21st bit:
                    xor     $0, 0x200000
                    # Set eflags:
                    push    $0
                    popfd
                    # Read eflags again, if cpuid is available
                    # the 21st bit will be flipped, otherwise it
                    # it will have the same value as the original in $1:
                    pushfd
                    pop     $0
                    # Xor'ing with the original eflags should have the
                    # 21st bit set to true if cpuid is available and zero
                    # otherwise. All other bits have not been modified and
                    # are zero:
                    xor     $0, $1
                    "#
                     : "=r"(result), "=r"(_temp)
                     :
                     : "cc", "memory"
                     : "intel");
            }
            // Therefore, if result is 0, the bit was not modified and cpuid is
            // not available. If cpuid is available, the bit was modified and
            // result != 0.
            result != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

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

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct MempoolConfig {
    pub capacity: usize,
    pub capacity_per_user: usize,
    // number of failovers to broadcast to when the primary network is alive
    pub default_failovers: usize,
    pub max_broadcasts_per_peer: usize,
    pub mempool_snapshot_interval_secs: u64,
    pub shared_mempool_ack_timeout_ms: u64,
    pub shared_mempool_backoff_interval_ms: u64,
    pub shared_mempool_batch_size: usize,
    pub shared_mempool_max_concurrent_inbound_syncs: usize,
    pub shared_mempool_tick_interval_ms: u64,
    pub system_transaction_timeout_secs: u64,
    pub system_transaction_gc_interval_ms: u64,
}

impl Default for MempoolConfig {
    fn default() -> MempoolConfig {
        MempoolConfig {
            shared_mempool_tick_interval_ms: 50,
            shared_mempool_backoff_interval_ms: 30_000,
            shared_mempool_batch_size: 100,
            shared_mempool_ack_timeout_ms: 2_000,
            shared_mempool_max_concurrent_inbound_syncs: 2,
            max_broadcasts_per_peer: 1,
            mempool_snapshot_interval_secs: 180,
            capacity: 1_000_000,
            capacity_per_user: 100,
            default_failovers: 0,
            system_transaction_timeout_secs: 86400,
            system_transaction_gc_interval_ms: 180_000,
        }
    }
}
<commit_msg>[mempool] config tweaks<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct MempoolConfig {
    pub capacity: usize,
    pub capacity_per_user: usize,
    // number of failovers to broadcast to when the primary network is alive
    pub default_failovers: usize,
    pub max_broadcasts_per_peer: usize,
    pub mempool_snapshot_interval_secs: u64,
    pub shared_mempool_ack_timeout_ms: u64,
    pub shared_mempool_backoff_interval_ms: u64,
    pub shared_mempool_batch_size: usize,
    pub shared_mempool_max_concurrent_inbound_syncs: usize,
    pub shared_mempool_tick_interval_ms: u64,
    pub system_transaction_timeout_secs: u64,
    pub system_transaction_gc_interval_ms: u64,
}

impl Default for MempoolConfig {
    fn default() -> MempoolConfig {
        MempoolConfig {
            shared_mempool_tick_interval_ms: 50,
            shared_mempool_backoff_interval_ms: 30_000,
            shared_mempool_batch_size: 100,
            shared_mempool_ack_timeout_ms: 2_000,
            shared_mempool_max_concurrent_inbound_syncs: 2,
            max_broadcasts_per_peer: 1,
            mempool_snapshot_interval_secs: 180,
            capacity: 1_000_000,
            capacity_per_user: 100,
            default_failovers: 0,
            system_transaction_timeout_secs: 600,
            system_transaction_gc_interval_ms: 60_000,
        }
    }
}
<|endoftext|>


<commit_before>use ra_parser::{Token, TokenSource};
use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T};
use std::cell::{Cell, RefCell};
use tt::buffer::{Cursor, TokenBuffer};

#[derive(Debug, Clone, Eq, PartialEq)]
struct TtToken {
    pub kind: SyntaxKind,
    pub is_joint_to_next: bool,
    pub text: SmolStr,
}

pub(crate) struct SubtreeTokenSource<'a> {
    cached_cursor: Cell<Cursor<'a>>,
    cached: RefCell<Vec<Option<TtToken>>>,
    curr: (Token, usize),
}

impl<'a> SubtreeTokenSource<'a> {
    // Helper function used in test
    #[cfg(test)]
    pub fn text(&self) -> SmolStr {
        match self.get(self.curr.1) {
            Some(tt) => tt.text,
            _ => SmolStr::new(""),
        }
    }
}

impl<'a> SubtreeTokenSource<'a> {
    pub fn new(buffer: &'a TokenBuffer) -> SubtreeTokenSource<'a> {
        let cursor = buffer.begin();

        let mut res = SubtreeTokenSource {
            curr: (Token { kind: EOF, is_jointed_to_next: false }, 0),
            cached_cursor: Cell::new(cursor),
            cached: RefCell::new(Vec::with_capacity(10)),
        };
        res.curr = (res.mk_token(0), 0);
        res
    }

    fn mk_token(&self, pos: usize) -> Token {
        match self.get(pos) {
            Some(tt) => Token { kind: tt.kind, is_jointed_to_next: tt.is_joint_to_next },
            None => Token { kind: EOF, is_jointed_to_next: false },
        }
    }

    fn get(&self, pos: usize) -> Option<TtToken> {
        let mut cached = self.cached.borrow_mut();
        if pos < cached.len() {
            return cached[pos].clone();
        }

        while pos >= cached.len() {
            let cursor = self.cached_cursor.get();
            if cursor.eof() {
                cached.push(None);
                continue;
            }

            match cursor.token_tree() {
                Some(tt::TokenTree::Leaf(leaf)) => {
                    cached.push(Some(convert_leaf(&leaf)));
                    self.cached_cursor.set(cursor.bump());
                }
                Some(tt::TokenTree::Subtree(subtree)) => {
                    self.cached_cursor.set(cursor.subtree().unwrap());
                    cached.push(Some(convert_delim(subtree.delimiter, false)));
                }
                None => {
                    if let Some(subtree) = cursor.end() {
                        cached.push(Some(convert_delim(subtree.delimiter, true)));
                        self.cached_cursor.set(cursor.bump());
                    }
                }
            }
        }

        cached[pos].clone()
    }
}

impl<'a> TokenSource for SubtreeTokenSource<'a> {
    fn current(&self) -> Token {
        self.curr.0
    }

    /// Lookahead n token
    fn lookahead_nth(&self, n: usize) -> Token {
        self.mk_token(self.curr.1 + n)
    }

    /// bump cursor to next token
    fn bump(&mut self) {
        if self.current().kind == EOF {
            return;
        }

        self.curr = (self.mk_token(self.curr.1 + 1), self.curr.1 + 1);
    }

    /// Is the current token a specified keyword?
    fn is_keyword(&self, kw: &str) -> bool {
        match self.get(self.curr.1) {
            Some(t) => t.text == *kw,
            _ => false,
        }
    }
}

fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken {
    let (kinds, texts) = match d {
        tt::Delimiter::Parenthesis => ([T!['('], T![')']], "()"),
        tt::Delimiter::Brace => ([T!['{'], T!['}']], "{}"),
        tt::Delimiter::Bracket => ([T!['['], T![']']], "[]"),
        tt::Delimiter::None => ([L_DOLLAR, R_DOLLAR], ""),
    };

    let idx = closing as usize;
    let kind = kinds[idx];
    let text = if texts.len() > 0 { &texts[idx..texts.len() - (1 - idx)] } else { "" };
    TtToken { kind, is_joint_to_next: false, text: SmolStr::new(text) }
}

fn convert_literal(l: &tt::Literal) -> TtToken {
    let kind =
        classify_literal(&l.text).map(|tkn| tkn.kind).unwrap_or_else(|| match l.text.as_ref() {
            "true" => T![true],
            "false" => T![false],
            _ => panic!("Fail to convert given literal {:#?}", &l),
        });

    TtToken { kind, is_joint_to_next: false, text: l.text.clone() }
}

fn convert_ident(ident: &tt::Ident) -> TtToken {
    let kind = if let Some('\'') = ident.text.chars().next() {
        LIFETIME
    } else {
        SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT)
    };

    TtToken { kind, is_joint_to_next: false, text: ident.text.clone() }
}

fn convert_punct(p: tt::Punct) -> TtToken {
    let kind = match p.char {
        // lexer may produce compound tokens for these ones
        '.' => T![.],
        ':' => T![:],
        '=' => T![=],
        '!' => T![!],
        '-' => T![-],
        c => SyntaxKind::from_char(c).unwrap(),
    };
    let text = {
        let mut buf = [0u8; 4];
        let s: &str = p.char.encode_utf8(&mut buf);
        SmolStr::new(s)
    };
    TtToken { kind, is_joint_to_next: p.spacing == tt::Spacing::Joint, text }
}

fn convert_leaf(leaf: &tt::Leaf) -> TtToken {
    match leaf {
        tt::Leaf::Literal(l) => convert_literal(l),
        tt::Leaf::Ident(ident) => convert_ident(ident),
        tt::Leaf::Punct(punct) => convert_punct(*punct),
    }
}
<commit_msg>Avoid cloning a TtToken in SubtreeTokenSource::mk_token<commit_after>use ra_parser::{Token, TokenSource};
use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T};
use std::cell::{Cell, RefCell};
use tt::buffer::{Cursor, TokenBuffer};

#[derive(Debug, Clone, Eq, PartialEq)]
struct TtToken {
    pub kind: SyntaxKind,
    pub is_joint_to_next: bool,
    pub text: SmolStr,
}

pub(crate) struct SubtreeTokenSource<'a> {
    cached_cursor: Cell<Cursor<'a>>,
    cached: RefCell<Vec<Option<TtToken>>>,
    curr: (Token, usize),
}

impl<'a> SubtreeTokenSource<'a> {
    // Helper function used in test
    #[cfg(test)]
    pub fn text(&self) -> SmolStr {
        let idx = self.get(self.curr.1);
        let cached = self.cached.borrow();
        match cached[idx] {
            Some(ref tt) => tt.text.clone(),
            _ => SmolStr::new(""),
        }
    }
}

impl<'a> SubtreeTokenSource<'a> {
    pub fn new(buffer: &'a TokenBuffer) -> SubtreeTokenSource<'a> {
        let cursor = buffer.begin();

        let mut res = SubtreeTokenSource {
            curr: (Token { kind: EOF, is_jointed_to_next: false }, 0),
            cached_cursor: Cell::new(cursor),
            cached: RefCell::new(Vec::with_capacity(10)),
        };
        res.curr = (res.mk_token(0), 0);
        res
    }

    fn mk_token(&self, pos: usize) -> Token {
        let idx = self.get(pos);
        let cached = self.cached.borrow();
        match cached[idx] {
            Some(ref tt) => Token { kind: tt.kind, is_jointed_to_next: tt.is_joint_to_next },
            None => Token { kind: EOF, is_jointed_to_next: false },
        }
    }

    fn get(&self, pos: usize) -> usize {
        let mut cached = self.cached.borrow_mut();
        if pos < cached.len() {
            return pos;
        }

        while pos >= cached.len() {
            let cursor = self.cached_cursor.get();
            if cursor.eof() {
                cached.push(None);
                continue;
            }

            match cursor.token_tree() {
                Some(tt::TokenTree::Leaf(leaf)) => {
                    cached.push(Some(convert_leaf(&leaf)));
                    self.cached_cursor.set(cursor.bump());
                }
                Some(tt::TokenTree::Subtree(subtree)) => {
                    self.cached_cursor.set(cursor.subtree().unwrap());
                    cached.push(Some(convert_delim(subtree.delimiter, false)));
                }
                None => {
                    if let Some(subtree) = cursor.end() {
                        cached.push(Some(convert_delim(subtree.delimiter, true)));
                        self.cached_cursor.set(cursor.bump());
                    }
                }
            }
        }

        pos
    }
}

impl<'a> TokenSource for SubtreeTokenSource<'a> {
    fn current(&self) -> Token {
        self.curr.0
    }

    /// Lookahead n token
    fn lookahead_nth(&self, n: usize) -> Token {
        self.mk_token(self.curr.1 + n)
    }

    /// bump cursor to next token
    fn bump(&mut self) {
        if self.current().kind == EOF {
            return;
        }

        self.curr = (self.mk_token(self.curr.1 + 1), self.curr.1 + 1);
    }

    /// Is the current token a specified keyword?
    fn is_keyword(&self, kw: &str) -> bool {
        let idx = self.get(self.curr.1);
        let cached = self.cached.borrow();
        match cached[idx] {
            Some(ref t) => t.text == *kw,
            _ => false,
        }
    }
}

fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken {
    let (kinds, texts) = match d {
        tt::Delimiter::Parenthesis => ([T!['('], T![')']], "()"),
        tt::Delimiter::Brace => ([T!['{'], T!['}']], "{}"),
        tt::Delimiter::Bracket => ([T!['['], T![']']], "[]"),
        tt::Delimiter::None => ([L_DOLLAR, R_DOLLAR], ""),
    };

    let idx = closing as usize;
    let kind = kinds[idx];
    let text = if texts.len() > 0 { &texts[idx..texts.len() - (1 - idx)] } else { "" };
    TtToken { kind, is_joint_to_next: false, text: SmolStr::new(text) }
}

fn convert_literal(l: &tt::Literal) -> TtToken {
    let kind =
        classify_literal(&l.text).map(|tkn| tkn.kind).unwrap_or_else(|| match l.text.as_ref() {
            "true" => T![true],
            "false" => T![false],
            _ => panic!("Fail to convert given literal {:#?}", &l),
        });

    TtToken { kind, is_joint_to_next: false, text: l.text.clone() }
}

fn convert_ident(ident: &tt::Ident) -> TtToken {
    let kind = if let Some('\'') = ident.text.chars().next() {
        LIFETIME
    } else {
        SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT)
    };

    TtToken { kind, is_joint_to_next: false, text: ident.text.clone() }
}

fn convert_punct(p: tt::Punct) -> TtToken {
    let kind = match p.char {
        // lexer may produce compound tokens for these ones
        '.' => T![.],
        ':' => T![:],
        '=' => T![=],
        '!' => T![!],
        '-' => T![-],
        c => SyntaxKind::from_char(c).unwrap(),
    };
    let text = {
        let mut buf = [0u8; 4];
        let s: &str = p.char.encode_utf8(&mut buf);
        SmolStr::new(s)
    };
    TtToken { kind, is_joint_to_next: p.spacing == tt::Spacing::Joint, text }
}

fn convert_leaf(leaf: &tt::Leaf) -> TtToken {
    match leaf {
        tt::Leaf::Literal(l) => convert_literal(l),
        tt::Leaf::Ident(ident) => convert_ident(ident),
        tt::Leaf::Punct(punct) => convert_punct(*punct),
    }
}
<|endoftext|>


<commit_before>extern crate phf;

#[cfg(test)]
mod test {
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));

    #[test]
    fn map() {
        assert_eq!("a", MAP[&1]);
        assert_eq!("b", MAP[&2]);
        assert_eq!("c", MAP[&3]);
        assert!(!MAP.contains_key(&100));
    }

    #[test]
    fn set() {
        assert!(SET.contains(&1));
        assert!(SET.contains(&2));
        assert!(SET.contains(&3));
        assert!(!SET.contains(&4));
    }

    #[test]
    fn ordered_map() {
        assert_eq!("a", ORDERED_MAP[&1]);
        assert_eq!("b", ORDERED_MAP[&2]);
        assert_eq!("c", ORDERED_MAP[&3]);
        assert!(!ORDERED_MAP.contains_key(&100));
        assert_eq!(&["a", "b", "c"][..], ORDERED_MAP.values().cloned().collect::<Vec<_>>());
    }

    #[test]
    fn ordered_set() {
        assert!(ORDERED_SET.contains(&1));
        assert!(ORDERED_SET.contains(&2));
        assert!(ORDERED_SET.contains(&3));
        assert!(!ORDERED_SET.contains(&4));
        assert_eq!(&[1, 2, 3][..], ORDERED_SET.iter().cloned().collect::<Vec<_>>());
    }

    #[test]
    fn str_keys() {
        assert_eq!(1, STR_KEYS["a"]);
        assert_eq!(2, STR_KEYS["b"]);
        assert_eq!(3, STR_KEYS["c"]);
    }
}
<commit_msg>Fix codegen tests<commit_after>extern crate phf;

#[cfg(test)]
mod test {
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));

    #[test]
    fn map() {
        assert_eq!("a", MAP[&1]);
        assert_eq!("b", MAP[&2]);
        assert_eq!("c", MAP[&3]);
        assert!(!MAP.contains_key(&100));
    }

    #[test]
    fn set() {
        assert!(SET.contains(&1));
        assert!(SET.contains(&2));
        assert!(SET.contains(&3));
        assert!(!SET.contains(&4));
    }

    #[test]
    fn ordered_map() {
        assert_eq!("a", ORDERED_MAP[&1]);
        assert_eq!("b", ORDERED_MAP[&2]);
        assert_eq!("c", ORDERED_MAP[&3]);
        assert!(!ORDERED_MAP.contains_key(&100));
        assert_eq!(&["a", "b", "c"][..], &ORDERED_MAP.values().cloned().collect::<Vec<_>>()[..]);
    }

    #[test]
    fn ordered_set() {
        assert!(ORDERED_SET.contains(&1));
        assert!(ORDERED_SET.contains(&2));
        assert!(ORDERED_SET.contains(&3));
        assert!(!ORDERED_SET.contains(&4));
        assert_eq!(&[1, 2, 3][..], &ORDERED_SET.iter().cloned().collect::<Vec<_>>()[..]);
    }

    #[test]
    fn str_keys() {
        assert_eq!(1, STR_KEYS["a"]);
        assert_eq!(2, STR_KEYS["b"]);
        assert_eq!(3, STR_KEYS["c"]);
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate rgen3_save;
extern crate rgen3_string;

use rand::{thread_rng, Rng, ThreadRng};
use rgen3_save::{Pokemon, SaveSections, TrainerInfo};
use std::collections::HashSet;

static PREFIX_NAMES: [&'static str; 52] = [
    "Acid", "Axel", "Baal", "Bike", "Bull", "Bald", "Cave", "Diet", "Dray", "Duke", "Easy", "Fact",
    "Face", "Fowl", "Fuzz", "Goat", "Hair", "Head", "Hiss", "Idea", "Iris", "Iron", "Jack", "John",
    "Kart", "Lady", "Limb", "Lime", "Mace", "Mars", "Naga", "Nuke", "Nude", "Omen", "Orca", "Poke",
    "Pyre", "Quiz", "Risk", "Road", "Sock", "Swag", "Teal", "Tree", "Ugly", "Vamp", "Vibe", "Wolf",
    "Xray", "Yoga", "Zeta", "Zoom",
];

static SUFFIX_NAMES: [&'static str; 24] = [
    "Adder", "Baker", "Biter", "Coder", "Curer", "Diver", "Eater", "Faker", "Flier", "Frier",
    "Gamer", "Gazer", "Giver", "Laser", "Lover", "Maker", "Order", "Racer", "Taker", "Tamer",
    "Voter", "Waker", "Zoner", "Hugger",
];

struct PokeGen<'a> {
    chosen_names: HashSet<String>,
    chosen_species: HashSet<u16>,
    n_unique: u16,
    trainer: &'a TrainerInfo,
    rng: ThreadRng,
}

impl<'a> PokeGen<'a> {
    fn new(trainer: &'a TrainerInfo) -> Self {
        PokeGen {
            chosen_names: HashSet::new(),
            chosen_species: HashSet::new(),
            n_unique: 0,
            trainer: trainer,
            rng: thread_rng(),
        }
    }
    fn gen(&mut self) -> Pokemon {
        let mut pokemon = Pokemon::default();
        let mut name;
        loop {
            let prefix = self.rng.choose(&PREFIX_NAMES).unwrap();
            let suffix = self.rng.choose(&SUFFIX_NAMES).unwrap();
            name = format!("{} {}", prefix, suffix);
            // Make sure we don't use the same name twice in our team
            if !self.chosen_names.contains(&name) {
                break;
            }
        }
        rgen3_string::encode_string(&name, &mut pokemon.nickname.0);
        self.chosen_names.insert(name);
        {
            loop {
                let species = self.rng.gen_range(1, 412);
                let result = pokemon.set_species(species);
                if result.is_ok() {
                    if self.chosen_species.contains(&species) {
                        if self.n_unique >= 386 {
                            break;
                        }
                    } else {
                        assert!(self.chosen_species.insert(species));
                        self.n_unique += 1;
                        break;
                    }
                }
            }
            pokemon.data.growth.experience = 1_640_000;
            pokemon.data.growth.friendship = 0xFF;
            pokemon.data.growth.pp_bonuses = 0xFF;
            pokemon.data.attacks.move1 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move2 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move3 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move4 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.pp1 = 99;
            pokemon.data.attacks.pp2 = 99;
            pokemon.data.attacks.pp3 = 99;
            pokemon.data.attacks.pp4 = 99;
            pokemon.data.evs_and_condition.hp = 0xFF;
            pokemon.data.evs_and_condition.attack = 0xFF;
            pokemon.data.evs_and_condition.defense = 0xFF;
            pokemon.data.evs_and_condition.speed = 0xFF;
            pokemon.data.evs_and_condition.sp_attack = 0xFF;
            pokemon.data.evs_and_condition.sp_defense = 0xFF;
            pokemon.data.evs_and_condition.coolness = 0xFF;
            pokemon.data.evs_and_condition.beauty = 0xFF;
            pokemon.data.evs_and_condition.cuteness = 0xFF;
            pokemon.data.evs_and_condition.smartness = 0xFF;
            pokemon.data.evs_and_condition.toughness = 0xFF;
            pokemon.ot_id = self.trainer.full_id();
            pokemon.ot_name = self.trainer.name;
        }
        pokemon
    }
}

fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().expect("Need path to save as first arg");
    let mut save = rgen3_save::Save::load_from_file(&path).unwrap();
    {
        let SaveSections {
            trainer, pc_boxes, ..
        } = save.sections();
        let mut generator = PokeGen::new(trainer);
        for b in pc_boxes.iter_mut() {
            for p in &mut b.pokemon {
                *p = Some(generator.gen());
            }
        }
    }
    save.save_to_file(path).unwrap();
}
<commit_msg>Revert "fill-pc example: Add "Hugger" to suffix names"<commit_after>extern crate rand;
extern crate rgen3_save;
extern crate rgen3_string;

use rand::{thread_rng, Rng, ThreadRng};
use rgen3_save::{Pokemon, SaveSections, TrainerInfo};
use std::collections::HashSet;

static PREFIX_NAMES: [&'static str; 52] = [
    "Acid", "Axel", "Baal", "Bike", "Bull", "Bald", "Cave", "Diet", "Dray", "Duke", "Easy", "Fact",
    "Face", "Fowl", "Fuzz", "Goat", "Hair", "Head", "Hiss", "Idea", "Iris", "Iron", "Jack", "John",
    "Kart", "Lady", "Limb", "Lime", "Mace", "Mars", "Naga", "Nuke", "Nude", "Omen", "Orca", "Poke",
    "Pyre", "Quiz", "Risk", "Road", "Sock", "Swag", "Teal", "Tree", "Ugly", "Vamp", "Vibe", "Wolf",
    "Xray", "Yoga", "Zeta", "Zoom",
];

static SUFFIX_NAMES: [&'static str; 23] = [
    "Adder", "Baker", "Biter", "Coder", "Curer", "Diver", "Eater", "Faker", "Flier", "Frier",
    "Gamer", "Gazer", "Giver", "Laser", "Lover", "Maker", "Order", "Racer", "Taker", "Tamer",
    "Voter", "Waker", "Zoner",
];

struct PokeGen<'a> {
    chosen_names: HashSet<String>,
    chosen_species: HashSet<u16>,
    n_unique: u16,
    trainer: &'a TrainerInfo,
    rng: ThreadRng,
}

impl<'a> PokeGen<'a> {
    fn new(trainer: &'a TrainerInfo) -> Self {
        PokeGen {
            chosen_names: HashSet::new(),
            chosen_species: HashSet::new(),
            n_unique: 0,
            trainer: trainer,
            rng: thread_rng(),
        }
    }
    fn gen(&mut self) -> Pokemon {
        let mut pokemon = Pokemon::default();
        let mut name;
        loop {
            let prefix = self.rng.choose(&PREFIX_NAMES).unwrap();
            let suffix = self.rng.choose(&SUFFIX_NAMES).unwrap();
            name = format!("{} {}", prefix, suffix);
            // Make sure we don't use the same name twice in our team
            if !self.chosen_names.contains(&name) {
                break;
            }
        }
        rgen3_string::encode_string(&name, &mut pokemon.nickname.0);
        self.chosen_names.insert(name);
        {
            loop {
                let species = self.rng.gen_range(1, 412);
                let result = pokemon.set_species(species);
                if result.is_ok() {
                    if self.chosen_species.contains(&species) {
                        if self.n_unique >= 386 {
                            break;
                        }
                    } else {
                        assert!(self.chosen_species.insert(species));
                        self.n_unique += 1;
                        break;
                    }
                }
            }
            pokemon.data.growth.experience = 1_640_000;
            pokemon.data.growth.friendship = 0xFF;
            pokemon.data.growth.pp_bonuses = 0xFF;
            pokemon.data.attacks.move1 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move2 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move3 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move4 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.pp1 = 99;
            pokemon.data.attacks.pp2 = 99;
            pokemon.data.attacks.pp3 = 99;
            pokemon.data.attacks.pp4 = 99;
            pokemon.data.evs_and_condition.hp = 0xFF;
            pokemon.data.evs_and_condition.attack = 0xFF;
            pokemon.data.evs_and_condition.defense = 0xFF;
            pokemon.data.evs_and_condition.speed = 0xFF;
            pokemon.data.evs_and_condition.sp_attack = 0xFF;
            pokemon.data.evs_and_condition.sp_defense = 0xFF;
            pokemon.data.evs_and_condition.coolness = 0xFF;
            pokemon.data.evs_and_condition.beauty = 0xFF;
            pokemon.data.evs_and_condition.cuteness = 0xFF;
            pokemon.data.evs_and_condition.smartness = 0xFF;
            pokemon.data.evs_and_condition.toughness = 0xFF;
            pokemon.ot_id = self.trainer.full_id();
            pokemon.ot_name = self.trainer.name;
        }
        pokemon
    }
}

fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().expect("Need path to save as first arg");
    let mut save = rgen3_save::Save::load_from_file(&path).unwrap();
    {
        let SaveSections {
            trainer, pc_boxes, ..
        } = save.sections();
        let mut generator = PokeGen::new(trainer);
        for b in pc_boxes.iter_mut() {
            for p in &mut b.pokemon {
                *p = Some(generator.gen());
            }
        }
    }
    save.save_to_file(path).unwrap();
}
<|endoftext|>


<commit_before>#![feature(test)]
#![feature(core)]
#![allow(unused_imports)]

extern crate eve;
extern crate test;
extern crate core;

use eve::interpreter::*;
use eve::value::*;
use eve::test::*;
use eve::query::Ref;

// Macro for creating expression vectors
macro_rules! exprvec {
    ( $( $x:expr ),* ) => {
    	{
    		vec![$($x.to_expr(),)*]
        }
    };
}

#[allow(dead_code)]
fn main() {

	/*
	let c1 = Call{fun: EveFn::Sum, args: exprvec![1.3,2]};
	let result = evaluate(&c1.to_expr(),&vec![]);
	println!("{:?}",result);
	*/
}

#[test]
fn match_test(){

	// Test a single match
	let input2 = Expression::Ref(Ref::Constant{value: 4.to_value()});

	let patterns2 = vec!(Pattern::Constant(Ref::Constant{value: 1.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 2.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 3.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 4.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 5.to_value()}),
					   );
	let handlers2 = exprvec!["oneone","twotwo","threethree","fourfour","fivefive"];

	let m2 = Match{input: input2, patterns: patterns2, handlers: handlers2};

	let result = evaluate(&m2.clone().to_expr(),&vec![]);

	assert_eq!(result,"fourfour".to_value());

	// Test a nested match
	let input = Expression::Ref(Ref::Constant{value: 3.to_value()});

	let patterns = vec!(Pattern::Constant(Ref::Constant{value: 1.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 2.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 3.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 4.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 5.to_value()}),
					   );
	let handlers = exprvec!["one","two",m2,"four","five"];

	let m1 = Match{input: input, patterns: patterns, handlers: handlers};

	let result = evaluate(&m1.to_expr(),&vec![]);

	assert_eq!(result,"fourfour".to_value());
}

#[test]
fn opstest() {

	// Test Some General Math Ops: (((1.3 + 2) * 3) + (7 - 4) / 10) ^ 2.5
	let c1 = Call{fun: EveFn::Add, args: exprvec![1.3,2]};				// C1 = 1.3 + 2
	let c2 = Call{fun: EveFn::Multiply, args: exprvec![c1,3]};			// C2 = C1 * 3
	let c3 = Call{fun: EveFn::Subtract, args: exprvec![7,4]};			// C3 = 7 - 4
	let c4 = Call{fun: EveFn::Divide, args: exprvec![c3,10]};			// C4 = C3 / 10
	let c5 = Call{fun: EveFn::Add, args: exprvec![c2,c4]};				// C5 = C2 + C4
	let c6 = Call{fun: EveFn::Exponentiate, args: exprvec![c5,2.5]};	// C6 = C5 ^ 2.5
	let result = evaluate(&c6.to_expr(),&vec![]);
	assert_eq!(result,(((1.3f64 + 2f64) * 3f64) + (7f64 - 4f64) / 10f64).powf(2.5f64).to_value());

}

#[test]
fn stringtest() {

	// Test a text replacement
	let c1 = Call{fun: EveFn::StrReplace, args: exprvec!["Hello World","l","q"] };
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result.as_str(),"Heqqo Worqd");

}

#[test]
fn trigtest() {

	let pi = std::f64::consts::PI;

	// sin
	let c1 = Call{fun: EveFn::Sin, args: exprvec![pi]};
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result,pi.sin().to_value());

	// cos
	let c1 = Call{fun: EveFn::Cos, args: exprvec![pi]};
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result,pi.cos().to_value());

	// tan
	let c1 = Call{fun: EveFn::Tan, args: exprvec![pi]};
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result,pi.tan().to_value());

	// atan2
	let c1 = Call{fun: EveFn::ATan2, args: exprvec![1.2,2.3]};
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result,1.2f64.atan2(2.3f64).to_value());
}

#[test]
fn bigmathtest() {

	let wa = 1.5;
	let ma = 2.3;
	let va = 11.3;
	let ga = 0.34;
	let mu = 1.50;
	let gd = 3.14;
	let g = 9.8;
	let wx = 0.04;
	let ps = 0.013;
	let rh = 1.74;

	let c1 = Call{fun: EveFn::Sin, args: exprvec![ga]}; 			// sin(ga)
	let c2 = Call{fun: EveFn::Exponentiate, args: exprvec![c1,2]}; 	// sin(ga)^2
	let c3 = Call{fun: EveFn::Multiply, args: exprvec![wx,c2]}; 	// wx*sin(ga)^2
	let c4 = Call{fun: EveFn::Sin, args: exprvec![ps]}; 			// sin(ps)
	let c5 = Call{fun: EveFn::Multiply, args: exprvec![c3,c4]}; 	// wx*sin(ga)^2*sin(ps)

	let c6 = Call{fun: EveFn::Cos, args: exprvec![ga]}; 			// cos(ga)
	let c7 = Call{fun: EveFn::Multiply, args: exprvec![g,c6]}; 		// g*cos(ga)
	let c8 = Call{fun: EveFn::Divide, args: exprvec![c7,va]}; 		// g*cos(ga)/va
	let c9 = Call{fun: EveFn::Add, args: exprvec![gd,c8]}; 			// gd+g*cos(ga)/va

	let c10 = Call{fun: EveFn::Subtract, args: exprvec![c9,c5]}; 	// (gd+g*cos(ga)/va) - (wx*sin(ga)^2*sin(ps))

	let c11 = Call{fun: EveFn::Multiply, args: exprvec![wa,rh]};	// wa*rh
	let c12 = Call{fun: EveFn::Multiply, args: exprvec![c11,va]};	// wa*rh*va
	let c13 = Call{fun: EveFn::Cos, args: exprvec![mu]}; 			// cos(mu)
	let c14 = Call{fun: EveFn::Multiply, args: exprvec![c12,c13]};	// wa*rh*va*cos(mu)

	let c15 = Call{fun: EveFn::Multiply, args: exprvec![2,ma]};		// 2*ma

	let c16 = Call{fun: EveFn::Divide, args: exprvec![c15,c14]};	// 2*ma/wa*rh*va*cos(mu)

	let c17 = Call{fun: EveFn::Multiply, args: exprvec![c16,c10]};	// (2*ma/wa*rh*va*cos(mu)) * (gd+g*cos(ga)/va) - (wx*sin(ga)^2*sin(ps))

	let result = evaluate(&c17.to_expr(),&vec![]);

	assert_eq!(result,(2f64*ma/(wa*rh*va*mu.cos())*(gd+g*ga.cos()/va-wx*(ga.sin().powf(2f64))*ps.sin())).to_value());

}

#[bench]
fn opsbench(b: &mut test::Bencher) {

	// Test Some General Math Ops: (((1 + 2) * 3) + (7 - 4) / 10) ^ 2
	let c1 = Call{fun: EveFn::Add, args: exprvec![1.3,2]};				// C1 = 1.3 + 2
	let c2 = Call{fun: EveFn::Multiply, args: exprvec![c1,3]};			// C2 = C1 * 3
	let c3 = Call{fun: EveFn::Subtract, args: exprvec![7,4]};			// C3 = 7 - 4
	let c4 = Call{fun: EveFn::Divide, args: exprvec![c3,10]};			// C4 = C3 / 10
	let c5 = Call{fun: EveFn::Add, args: exprvec![c2,c4]};				// C5 = C2 + C4
	let c6 = Call{fun: EveFn::Exponentiate, args: exprvec![c5,2.5]};	// C6 = C5 ^ 2.5
	let e1 = c6.to_expr();

	b.iter(|| {
		evaluate(&e1,&vec![])
	});
}

#[bench]
fn bigmathbench(b: &mut test::Bencher) {

	let wa = 1.5;
	let ma = 2.3;
	let va = 11.3;
	let ga = 0.34;
	let mu = 1.50;
	let gd = 3.14;
	let g = 9.8;
	let wx = 0.04;
	let ps = 0.013;
	let rh = 1.74;

	let c1 = Call{fun: EveFn::Sin, args: exprvec![ga]}; 			// sin(ga)
	let c2 = Call{fun: EveFn::Exponentiate, args: exprvec![c1,2]}; 	// sin(ga)^2
	let c3 = Call{fun: EveFn::Multiply, args: exprvec![wx,c2]}; 	// wx*sin(ga)^2
	let c4 = Call{fun: EveFn::Sin, args: exprvec![ps]}; 			// sin(ps)
	let c5 = Call{fun: EveFn::Multiply, args: exprvec![c3,c4]}; 	// wx*sin(ga)^2*sin(ps)

	let c6 = Call{fun: EveFn::Cos, args: exprvec![ga]}; 			// cos(ga)
	let c7 = Call{fun: EveFn::Multiply, args: exprvec![g,c6]}; 		// g*cos(ga)
	let c8 = Call{fun: EveFn::Divide, args: exprvec![c7,va]}; 		// g*cos(ga)/va
	let c9 = Call{fun: EveFn::Add, args: exprvec![gd,c8]}; 			// gd+g*cos(ga)/va

	let c10 = Call{fun: EveFn::Subtract, args: exprvec![c9,c5]}; 	// (gd+g*cos(ga)/va) - (wx*sin(ga)^2*sin(ps))

	let c11 = Call{fun: EveFn::Multiply, args: exprvec![wa,rh]};	// wa*rh
	let c12 = Call{fun: EveFn::Multiply, args: exprvec![c11,va]};	// wa*rh*va
	let c13 = Call{fun: EveFn::Cos, args: exprvec![mu]}; 			// cos(mu)
	let c14 = Call{fun: EveFn::Multiply, args: exprvec![c12,c13]};	// wa*rh*va*cos(mu)

	let c15 = Call{fun: EveFn::Multiply, args: exprvec![2,ma]};		// 2*ma

	let c16 = Call{fun: EveFn::Divide, args: exprvec![c15,c14]};	// 2*ma/wa*rh*va*cos(mu)

	let c17 = Call{fun: EveFn::Multiply, args: exprvec![c16,c10]};	// (2*ma/wa*rh*va*cos(mu)) * (gd+g*cos(ga)/va) - (wx*sin(ga)^2*sin(ps))

	let e1 = c17.to_expr();

	b.iter(|| {
		evaluate(&e1,&vec![])
	});

}<commit_msg>Test splitting words<commit_after>#![feature(test)]
#![feature(core)]
#![allow(unused_imports)]

extern crate eve;
extern crate test;
extern crate core;

use eve::interpreter::*;
use eve::value::*;
use eve::test::*;
use eve::query::Ref;

// Macro for creating expression vectors
macro_rules! exprvec {
    ( $( $x:expr ),* ) => {
    	{
    		vec![$($x.to_expr(),)*]
        }
    };
}

#[allow(dead_code)]
fn main() {

}

#[test]
fn match_test(){

	// Test a single match
	let input2 = Expression::Ref(Ref::Constant{value: 4.to_value()});

	let patterns2 = vec!(Pattern::Constant(Ref::Constant{value: 1.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 2.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 3.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 4.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 5.to_value()}),
					   );
	let handlers2 = exprvec!["oneone","twotwo","threethree","fourfour","fivefive"];

	let m2 = Match{input: input2, patterns: patterns2, handlers: handlers2};

	let result = evaluate(&m2.clone().to_expr(),&vec![]);

	assert_eq!(result,"fourfour".to_value());

	// Test a nested match
	let input = Expression::Ref(Ref::Constant{value: 3.to_value()});

	let patterns = vec!(Pattern::Constant(Ref::Constant{value: 1.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 2.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 3.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 4.to_value()}),
					     Pattern::Constant(Ref::Constant{value: 5.to_value()}),
					   );
	let handlers = exprvec!["one","two",m2,"four","five"];

	let m1 = Match{input: input, patterns: patterns, handlers: handlers};

	let result = evaluate(&m1.to_expr(),&vec![]);

	assert_eq!(result,"fourfour".to_value());
}

#[test]
fn opstest() {

	// Test Some General Math Ops: (((1.3 + 2) * 3) + (7 - 4) / 10) ^ 2.5
	let c1 = Call{fun: EveFn::Add, args: exprvec![1.3,2]};				// C1 = 1.3 + 2
	let c2 = Call{fun: EveFn::Multiply, args: exprvec![c1,3]};			// C2 = C1 * 3
	let c3 = Call{fun: EveFn::Subtract, args: exprvec![7,4]};			// C3 = 7 - 4
	let c4 = Call{fun: EveFn::Divide, args: exprvec![c3,10]};			// C4 = C3 / 10
	let c5 = Call{fun: EveFn::Add, args: exprvec![c2,c4]};				// C5 = C2 + C4
	let c6 = Call{fun: EveFn::Exponentiate, args: exprvec![c5,2.5]};	// C6 = C5 ^ 2.5
	let result = evaluate(&c6.to_expr(),&vec![]);
	assert_eq!(result,(((1.3f64 + 2f64) * 3f64) + (7f64 - 4f64) / 10f64).powf(2.5f64).to_value());

}

#[test]
fn stringtest() {

	// Test a text replacement
	let c1 = Call{fun: EveFn::StrReplace, args: exprvec!["Hello World","l","q"] };
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result.as_str(),"Heqqo Worqd");

	// Test splitting words
	let c1 = Call{fun: EveFn::StrSplit, args: exprvec!["Hello World"] };
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result[0].as_str(),"Hello");
	assert_eq!(result[1].as_str(),"World");

}

#[test]
fn trigtest() {

	let pi = std::f64::consts::PI;

	// sin
	let c1 = Call{fun: EveFn::Sin, args: exprvec![pi]};
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result,pi.sin().to_value());

	// cos
	let c1 = Call{fun: EveFn::Cos, args: exprvec![pi]};
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result,pi.cos().to_value());

	// tan
	let c1 = Call{fun: EveFn::Tan, args: exprvec![pi]};
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result,pi.tan().to_value());

	// atan2
	let c1 = Call{fun: EveFn::ATan2, args: exprvec![1.2,2.3]};
	let result = evaluate(&c1.to_expr(),&vec![]);
	assert_eq!(result,1.2f64.atan2(2.3f64).to_value());
}

#[test]
fn bigmathtest() {

	let wa = 1.5;
	let ma = 2.3;
	let va = 11.3;
	let ga = 0.34;
	let mu = 1.50;
	let gd = 3.14;
	let g = 9.8;
	let wx = 0.04;
	let ps = 0.013;
	let rh = 1.74;

	let c1 = Call{fun: EveFn::Sin, args: exprvec![ga]}; 			// sin(ga)
	let c2 = Call{fun: EveFn::Exponentiate, args: exprvec![c1,2]}; 	// sin(ga)^2
	let c3 = Call{fun: EveFn::Multiply, args: exprvec![wx,c2]}; 	// wx*sin(ga)^2
	let c4 = Call{fun: EveFn::Sin, args: exprvec![ps]}; 			// sin(ps)
	let c5 = Call{fun: EveFn::Multiply, args: exprvec![c3,c4]}; 	// wx*sin(ga)^2*sin(ps)

	let c6 = Call{fun: EveFn::Cos, args: exprvec![ga]}; 			// cos(ga)
	let c7 = Call{fun: EveFn::Multiply, args: exprvec![g,c6]}; 		// g*cos(ga)
	let c8 = Call{fun: EveFn::Divide, args: exprvec![c7,va]}; 		// g*cos(ga)/va
	let c9 = Call{fun: EveFn::Add, args: exprvec![gd,c8]}; 			// gd+g*cos(ga)/va

	let c10 = Call{fun: EveFn::Subtract, args: exprvec![c9,c5]}; 	// (gd+g*cos(ga)/va) - (wx*sin(ga)^2*sin(ps))

	let c11 = Call{fun: EveFn::Multiply, args: exprvec![wa,rh]};	// wa*rh
	let c12 = Call{fun: EveFn::Multiply, args: exprvec![c11,va]};	// wa*rh*va
	let c13 = Call{fun: EveFn::Cos, args: exprvec![mu]}; 			// cos(mu)
	let c14 = Call{fun: EveFn::Multiply, args: exprvec![c12,c13]};	// wa*rh*va*cos(mu)

	let c15 = Call{fun: EveFn::Multiply, args: exprvec![2,ma]};		// 2*ma

	let c16 = Call{fun: EveFn::Divide, args: exprvec![c15,c14]};	// 2*ma/wa*rh*va*cos(mu)

	let c17 = Call{fun: EveFn::Multiply, args: exprvec![c16,c10]};	// (2*ma/wa*rh*va*cos(mu)) * (gd+g*cos(ga)/va) - (wx*sin(ga)^2*sin(ps))

	let result = evaluate(&c17.to_expr(),&vec![]);

	assert_eq!(result,(2f64*ma/(wa*rh*va*mu.cos())*(gd+g*ga.cos()/va-wx*(ga.sin().powf(2f64))*ps.sin())).to_value());

}

#[bench]
fn opsbench(b: &mut test::Bencher) {

	// Test Some General Math Ops: (((1 + 2) * 3) + (7 - 4) / 10) ^ 2
	let c1 = Call{fun: EveFn::Add, args: exprvec![1.3,2]};				// C1 = 1.3 + 2
	let c2 = Call{fun: EveFn::Multiply, args: exprvec![c1,3]};			// C2 = C1 * 3
	let c3 = Call{fun: EveFn::Subtract, args: exprvec![7,4]};			// C3 = 7 - 4
	let c4 = Call{fun: EveFn::Divide, args: exprvec![c3,10]};			// C4 = C3 / 10
	let c5 = Call{fun: EveFn::Add, args: exprvec![c2,c4]};				// C5 = C2 + C4
	let c6 = Call{fun: EveFn::Exponentiate, args: exprvec![c5,2.5]};	// C6 = C5 ^ 2.5
	let e1 = c6.to_expr();

	b.iter(|| {
		evaluate(&e1,&vec![])
	});
}

#[bench]
fn bigmathbench(b: &mut test::Bencher) {

	let wa = 1.5;
	let ma = 2.3;
	let va = 11.3;
	let ga = 0.34;
	let mu = 1.50;
	let gd = 3.14;
	let g = 9.8;
	let wx = 0.04;
	let ps = 0.013;
	let rh = 1.74;

	let c1 = Call{fun: EveFn::Sin, args: exprvec![ga]}; 			// sin(ga)
	let c2 = Call{fun: EveFn::Exponentiate, args: exprvec![c1,2]}; 	// sin(ga)^2
	let c3 = Call{fun: EveFn::Multiply, args: exprvec![wx,c2]}; 	// wx*sin(ga)^2
	let c4 = Call{fun: EveFn::Sin, args: exprvec![ps]}; 			// sin(ps)
	let c5 = Call{fun: EveFn::Multiply, args: exprvec![c3,c4]}; 	// wx*sin(ga)^2*sin(ps)

	let c6 = Call{fun: EveFn::Cos, args: exprvec![ga]}; 			// cos(ga)
	let c7 = Call{fun: EveFn::Multiply, args: exprvec![g,c6]}; 		// g*cos(ga)
	let c8 = Call{fun: EveFn::Divide, args: exprvec![c7,va]}; 		// g*cos(ga)/va
	let c9 = Call{fun: EveFn::Add, args: exprvec![gd,c8]}; 			// gd+g*cos(ga)/va

	let c10 = Call{fun: EveFn::Subtract, args: exprvec![c9,c5]}; 	// (gd+g*cos(ga)/va) - (wx*sin(ga)^2*sin(ps))

	let c11 = Call{fun: EveFn::Multiply, args: exprvec![wa,rh]};	// wa*rh
	let c12 = Call{fun: EveFn::Multiply, args: exprvec![c11,va]};	// wa*rh*va
	let c13 = Call{fun: EveFn::Cos, args: exprvec![mu]}; 			// cos(mu)
	let c14 = Call{fun: EveFn::Multiply, args: exprvec![c12,c13]};	// wa*rh*va*cos(mu)

	let c15 = Call{fun: EveFn::Multiply, args: exprvec![2,ma]};		// 2*ma

	let c16 = Call{fun: EveFn::Divide, args: exprvec![c15,c14]};	// 2*ma/wa*rh*va*cos(mu)

	let c17 = Call{fun: EveFn::Multiply, args: exprvec![c16,c10]};	// (2*ma/wa*rh*va*cos(mu)) * (gd+g*cos(ga)/va) - (wx*sin(ga)^2*sin(ps))

	let e1 = c17.to_expr();

	b.iter(|| {
		evaluate(&e1,&vec![])
	});

}<|endoftext|>


<commit_before>extern crate time;

use std::ascii::AsciiExt;

use time::get_time;

#[must_use]
fn match_char(e1: &u8, e2: &u8, ignore_case: bool) -> bool {
    if ignore_case {
        // FIXME: redis uses tolower() which is locale aware
        return e1.to_ascii_lowercase() == e2.to_ascii_lowercase();
    } else {
        return e1 == e2;
    }
}

pub fn glob_match(pattern: &Vec<u8>, element: &Vec<u8>, ignore_case: bool) -> bool {
    let mut patternpos = 0;
    let mut elementpos = 0;
    let star = 42u8; /* '*' */
    let question_mark = 63u8; /* '?' */
    let backslash = 92u8; /* '\\' */
    let open_bracket = 91u8; /* '[' */
    let close_bracket = 93u8; /* '[' */
    while patternpos < pattern.len() {
        match pattern[patternpos] {
            x if x == star => {
                while patternpos + 1 < pattern.len() && pattern[patternpos + 1] == star {
                    patternpos += 1;
                }
                if patternpos == pattern.len() {
                    return true;
                }
                for i in elementpos..(element.len() + 1) {
                    if glob_match(&pattern[patternpos + 1..].to_vec(), &element[i..].to_vec(), ignore_case) {
                        return true;
                    }
                }
                return false;
            },
            x if x == question_mark => {
                if elementpos >= element.len() {
                    return false;
                }
                elementpos += 1;
            },
            x if x == backslash => {
                patternpos += 1;
                if elementpos >= element.len(){
                    return false;
                }
                if !match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                    return false;
                }
                elementpos += 1;
            },
            x if x == open_bracket => {
                patternpos += 1;
                let not = pattern[patternpos] == ('^' as u8);
                if not {
                    patternpos += 1;
                }
                let mut matched = false;
                loop {
                    if pattern[patternpos] == backslash {
                        patternpos += 1;
                        if pattern[patternpos] == element[elementpos] {
                            matched = true;
                        }
                    } else if pattern[patternpos] == close_bracket {
                        break;
                    } else if patternpos >= pattern.len() {
                        patternpos += 1;
                        break;
                    } else if pattern.len() >= patternpos + 3 && pattern[patternpos + 1] == ('-' as u8) {
                        let mut start = pattern[patternpos];
                        let mut end = pattern[patternpos + 2];
                        let mut c = element[elementpos];
                        if start > end {
                            let t = start;
                            start = end;
                            end = t;
                        }
                        if ignore_case {
                            start = start.to_ascii_lowercase();
                            end = end.to_ascii_lowercase();
                            c = c.to_ascii_lowercase();
                        }
                        patternpos += 2;
                        if c >= start && c <= end {
                            matched = true;
                        }
                    } else {
                        if match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                            matched = true;
                        }
                    }
                    patternpos += 1;
                }
                if not {
                    matched = !matched;
                }
                if !matched {
                    return false;
                }
                elementpos += 1;
            },
            _ => {
                if elementpos >= element.len(){
                    return false;
                }
                if !match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                    return false;
                }
                elementpos += 1;
            },
        }
        patternpos += 1;
        if elementpos == element.len() {
            for p in patternpos..pattern.len() {
                if pattern[p] != star {
                    break;
                }
            }
            break;
        }
    }

    if patternpos == pattern.len() && elementpos == element.len() {
        return true;
    }
    return false;
}

pub fn ustime() -> i64 {
    let tv = get_time();
    tv.sec * 1000000 + tv.nsec as i64
}

pub fn mstime() -> i64 {
    ustime() / 1000
}

#[test]
fn glob_match_empty() {
    assert!(glob_match(&b"".to_vec(), &b"".to_vec(), true));
}

#[test]
fn glob_match_star() {
    assert!(glob_match(&b"*".to_vec(), &b"".to_vec(), true));
    assert!(glob_match(&b"*".to_vec(), &b"hello world".to_vec(), true));
    assert!(glob_match(&b"**".to_vec(), &b"hello world".to_vec(), true));
    assert!(glob_match(&b"hello*".to_vec(), &b"hello world".to_vec(), true));
    assert!(glob_match(&b"*world".to_vec(), &b"hello world".to_vec(), true));
    assert!(!glob_match(&b"foo*".to_vec(), &b"hello world".to_vec(), true));
    assert!(!glob_match(&b"*bar".to_vec(), &b"hello world".to_vec(), true));
    assert!(!glob_match(&b"*bar".to_vec(), &b"".to_vec(), true));
}

#[test]
fn glob_match_question_mark() {
    assert!(!glob_match(&b"?".to_vec(), &b"".to_vec(), true));
    assert!(glob_match(&b"?".to_vec(), &b"a".to_vec(), true));
    assert!(!glob_match(&b"?".to_vec(), &b"aa".to_vec(), true));
    assert!(glob_match(&b"a?".to_vec(), &b"aa".to_vec(), true));
}

#[test]
fn glob_match_backslash() {
    assert!(glob_match(&b"\\*asd".to_vec(), &b"*asd".to_vec(), true));
    assert!(!glob_match(&b"\\*d".to_vec(), &b"*asd".to_vec(), true));
    assert!(glob_match(&b"\\?a".to_vec(), &b"?a".to_vec(), true));
    assert!(!glob_match(&b"\\?a".to_vec(), &b"ba".to_vec(), true));
}

#[test]
fn glob_match_brackets() {
    assert!(glob_match(&b"[abc]".to_vec(), &b"a".to_vec(), true));
    assert!(!glob_match(&b"[^abc]".to_vec(), &b"a".to_vec(), true));
    assert!(glob_match(&b"[abc]b".to_vec(), &b"ab".to_vec(), true));
    assert!(!glob_match(&b"[abc]".to_vec(), &b"ab".to_vec(), true));
    assert!(glob_match(&b"[\\]*]".to_vec(), &b"]".to_vec(), true));
    assert!(!glob_match(&b"[\\]*]".to_vec(), &b"a".to_vec(), true));
}
<commit_msg>Implement splitargs<commit_after>extern crate time;

use std::ascii::AsciiExt;

use time::get_time;

#[must_use]
fn match_char(e1: &u8, e2: &u8, ignore_case: bool) -> bool {
    if ignore_case {
        // FIXME: redis uses tolower() which is locale aware
        return e1.to_ascii_lowercase() == e2.to_ascii_lowercase();
    } else {
        return e1 == e2;
    }
}

pub fn glob_match(pattern: &Vec<u8>, element: &Vec<u8>, ignore_case: bool) -> bool {
    let mut patternpos = 0;
    let mut elementpos = 0;
    let star = 42u8; /* '*' */
    let question_mark = 63u8; /* '?' */
    let backslash = 92u8; /* '\\' */
    let open_bracket = 91u8; /* '[' */
    let close_bracket = 93u8; /* '[' */
    while patternpos < pattern.len() {
        match pattern[patternpos] {
            x if x == star => {
                while patternpos + 1 < pattern.len() && pattern[patternpos + 1] == star {
                    patternpos += 1;
                }
                if patternpos == pattern.len() {
                    return true;
                }
                for i in elementpos..(element.len() + 1) {
                    if glob_match(&pattern[patternpos + 1..].to_vec(), &element[i..].to_vec(), ignore_case) {
                        return true;
                    }
                }
                return false;
            },
            x if x == question_mark => {
                if elementpos >= element.len() {
                    return false;
                }
                elementpos += 1;
            },
            x if x == backslash => {
                patternpos += 1;
                if elementpos >= element.len(){
                    return false;
                }
                if !match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                    return false;
                }
                elementpos += 1;
            },
            x if x == open_bracket => {
                patternpos += 1;
                let not = pattern[patternpos] == ('^' as u8);
                if not {
                    patternpos += 1;
                }
                let mut matched = false;
                loop {
                    if pattern[patternpos] == backslash {
                        patternpos += 1;
                        if pattern[patternpos] == element[elementpos] {
                            matched = true;
                        }
                    } else if pattern[patternpos] == close_bracket {
                        break;
                    } else if patternpos >= pattern.len() {
                        patternpos += 1;
                        break;
                    } else if pattern.len() >= patternpos + 3 && pattern[patternpos + 1] == ('-' as u8) {
                        let mut start = pattern[patternpos];
                        let mut end = pattern[patternpos + 2];
                        let mut c = element[elementpos];
                        if start > end {
                            let t = start;
                            start = end;
                            end = t;
                        }
                        if ignore_case {
                            start = start.to_ascii_lowercase();
                            end = end.to_ascii_lowercase();
                            c = c.to_ascii_lowercase();
                        }
                        patternpos += 2;
                        if c >= start && c <= end {
                            matched = true;
                        }
                    } else {
                        if match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                            matched = true;
                        }
                    }
                    patternpos += 1;
                }
                if not {
                    matched = !matched;
                }
                if !matched {
                    return false;
                }
                elementpos += 1;
            },
            _ => {
                if elementpos >= element.len(){
                    return false;
                }
                if !match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                    return false;
                }
                elementpos += 1;
            },
        }
        patternpos += 1;
        if elementpos == element.len() {
            for p in patternpos..pattern.len() {
                if pattern[p] != star {
                    break;
                }
            }
            break;
        }
    }

    if patternpos == pattern.len() && elementpos == element.len() {
        return true;
    }
    return false;
}

pub fn ustime() -> i64 {
    let tv = get_time();
    tv.sec * 1000000 + tv.nsec as i64
}

pub fn mstime() -> i64 {
    ustime() / 1000
}

pub fn splitargs(args: &Vec<u8>) -> Result<Vec<Vec<u8>>, ()> {
    let mut i = 0;
    let mut result = Vec::new();
    for _ in args {
        while i < args.len() && (args[i] == 0 || (args[i] as char).is_whitespace()) { i += 1; }
        if i >=  args.len() { break; }
        let mut inq = false;
        let mut insq = false;
        let mut done = false;
        let mut current = Vec::new();
        while !done && i < args.len() {
            let p = args[i] as char;
            if inq {
                if p == '\\' && (args[i + 1] as char) == 'x' {
                    if let Some(c1) = (args[i + 2] as char).to_digit(16) {
                        if let Some(c2) = (args[i + 3] as char).to_digit(16) {
                            current.push((c1 * 16 + c2) as u8);
                            i += 3;
                        }
                    }
                } else if p == '"'{
                    // closing quote must be followed by a space or nothing at all
                    i += 1;
                    if i != args.len() && !(args[i] as char).is_whitespace() { return Err(()); }
                    inq = false;
                    done = true;
                } else if p == '\\' && i + 1 < args.len() {
                    i += 1;
                    let c = match args[i] as char {
                        'n' => '\n',
                        'r' => '\r',
                        't' => '\t',
                        // FIXME: Rust does not recognize '\a' and '\b'?
                        'b' => 'b',
                        'a' => 'a',
                        c => c as char,
                    } as u8;
                    current.push(c);
                } else {
                    current.push(args[i]);
                }
            } else if insq {
                if p == '\'' {
                    // closing quote must be followed by a space or nothing at all
                    i += 1;
                    if i != args.len() && !(args[i] as char).is_whitespace() { return Err(()); }
                    insq = false;
                    done = true;
                } else if p == '\\' && i + 1 < args.len() && (args[i + 1] as char == '\'') {
                    current.push(args[i + 1]);
                    i += 1;
                } else {
                    current.push(args[i]);
                }
            } else {
                match p as char {
                    ' ' => done = true,
                    '\t' => done = true,
                    '\n' => done = true,
                    '\r' => done = true,
                    '\0' => done = true,
                    '"' => inq = true,
                    '\'' => insq = true,
                    _ => current.push(args[i]),
                }
            }
            i += 1;
        }
        result.push(current);
        if i >=  args.len() {
            if inq || insq {
                return Err(());
            }
            break;
        }
    }
    Ok(result)
}

#[test]
fn glob_match_empty() {
    assert!(glob_match(&b"".to_vec(), &b"".to_vec(), true));
}

#[test]
fn glob_match_star() {
    assert!(glob_match(&b"*".to_vec(), &b"".to_vec(), true));
    assert!(glob_match(&b"*".to_vec(), &b"hello world".to_vec(), true));
    assert!(glob_match(&b"**".to_vec(), &b"hello world".to_vec(), true));
    assert!(glob_match(&b"hello*".to_vec(), &b"hello world".to_vec(), true));
    assert!(glob_match(&b"*world".to_vec(), &b"hello world".to_vec(), true));
    assert!(!glob_match(&b"foo*".to_vec(), &b"hello world".to_vec(), true));
    assert!(!glob_match(&b"*bar".to_vec(), &b"hello world".to_vec(), true));
    assert!(!glob_match(&b"*bar".to_vec(), &b"".to_vec(), true));
}

#[test]
fn glob_match_question_mark() {
    assert!(!glob_match(&b"?".to_vec(), &b"".to_vec(), true));
    assert!(glob_match(&b"?".to_vec(), &b"a".to_vec(), true));
    assert!(!glob_match(&b"?".to_vec(), &b"aa".to_vec(), true));
    assert!(glob_match(&b"a?".to_vec(), &b"aa".to_vec(), true));
}

#[test]
fn glob_match_backslash() {
    assert!(glob_match(&b"\\*asd".to_vec(), &b"*asd".to_vec(), true));
    assert!(!glob_match(&b"\\*d".to_vec(), &b"*asd".to_vec(), true));
    assert!(glob_match(&b"\\?a".to_vec(), &b"?a".to_vec(), true));
    assert!(!glob_match(&b"\\?a".to_vec(), &b"ba".to_vec(), true));
}

#[test]
fn glob_match_brackets() {
    assert!(glob_match(&b"[abc]".to_vec(), &b"a".to_vec(), true));
    assert!(!glob_match(&b"[^abc]".to_vec(), &b"a".to_vec(), true));
    assert!(glob_match(&b"[abc]b".to_vec(), &b"ab".to_vec(), true));
    assert!(!glob_match(&b"[abc]".to_vec(), &b"ab".to_vec(), true));
    assert!(glob_match(&b"[\\]*]".to_vec(), &b"]".to_vec(), true));
    assert!(!glob_match(&b"[\\]*]".to_vec(), &b"a".to_vec(), true));
}

#[test]
fn splitargs_quotes() {
    assert_eq!(splitargs(&b"\"\\x9f\"".to_vec()).unwrap(), vec![vec![159u8]]);
    assert_eq!(splitargs(&b"\"\"".to_vec()).unwrap(), vec![vec![]]);
    assert_eq!(splitargs(&b"\"\\thello\\n\"".to_vec()).unwrap(), vec![b"\thello\n".to_vec()]);
    assert!(splitargs(&b"\"a".to_vec()).is_err());
}

#[test]
fn splitargs_singlequotes() {
    assert_eq!(splitargs(&b"\'\\x9f\'".to_vec()).unwrap(), vec![b"\\x9f".to_vec()]);
    assert_eq!(splitargs(&b"\'\'".to_vec()).unwrap(), vec![vec![]]);
    assert_eq!(splitargs(&b"\'\\\'\'".to_vec()).unwrap(), vec![b"'".to_vec()]);
    assert_eq!(splitargs(&b"\'\\thello\\n\'".to_vec()).unwrap(), vec![b"\\thello\\n".to_vec()]);
    assert!(splitargs(&b"\'a".to_vec()).is_err());
}

#[test]
fn splitargs_misc() {
    assert_eq!(splitargs(&b"hello world".to_vec()).unwrap(), vec![b"hello".to_vec(), b"world".to_vec()]);
    assert_eq!(splitargs(&b"\'hello\' world".to_vec()).unwrap(), vec![b"hello".to_vec(), b"world".to_vec()]);
    assert_eq!(splitargs(&b"\"hello\" world".to_vec()).unwrap(), vec![b"hello".to_vec(), b"world".to_vec()]);
    assert!(splitargs(&b"\"hello\"world".to_vec()).is_err());
    assert!(splitargs(&b"\'hello\'world".to_vec()).is_err());
}
<|endoftext|>


<commit_before>// Copyright 2015 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 {Intrinsic, i, f, v};
use rustc::middle::ty;

macro_rules! p {
    ($name: expr, ($($inputs: tt),*) -> $output: tt) => {
        plain!(concat!("llvm.x86.", $name), ($($inputs),*) -> $output)
    }
}

pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> {
    Some(match name {
        "mm_movemask_ps" => p!("sse.movmsk.ps", (f32x4) -> i32),
        "mm_movemask_pd" => p!("sse2.movmsk.pd", (f64x2) -> i32),
        "mm_movemask_epi8" => p!("sse2.pmovmskb.128", (i8x16) -> i32),

        "mm_rsqrt_ps" => p!("sse.rsqrt.ps", (f32x4) -> f32x4),
        "mm_rcp_ps" => p!("sse.rcp.ps", (f32x4) -> f32x4),

        "mm_sqrt_ps" => plain!("llvm.sqrt.v4f32", (f32x4) -> f32x4),
        "mm_sqrt_pd" => plain!("llvm.sqrt.v2f64", (f64x2) -> f64x2),

        "mm_max_ps" => p!("sse.max.ps", (f32x4, f32x4) -> f32x4),
        "mm_max_pd" => p!("sse2.max.pd", (f64x2, f64x2) -> f64x2),

        "mm_min_ps" => p!("sse.min.ps", (f32x4, f32x4) -> f32x4),
        "mm_min_pd" => p!("sse2.min.pd", (f64x2, f64x2) -> f64x2),

        "mm_shuffle_epi8" => p!("ssse3.pshuf.b.128", (i8x16, i8x16) -> i8x16),

        "mm_adds_epi16" => p!("sse2.padds.w", (i16x8, i16x8) -> i16x8),
        "mm_adds_epi8" => p!("sse2.padds.b", (i8x16, i8x16) -> i8x16),
        "mm_adds_epu16" => p!("sse2.paddus.w", (i16x8, i16x8) -> i16x8),
        "mm_adds_epu8" => p!("sse2.paddus.b", (i8x16, i8x16) -> i8x16),
        "mm_avg_epu16" => p!("sse2.pavg.w", (i16x8, i16x8) -> i16x8),
        "mm_avg_epu8" => p!("sse2.pavg.b", (i8x16, i8x16) -> i8x16),
        "mm_madd_epi16" => p!("sse2.pmadd.wd", (i16x8, i16x8) -> i32x4),
        "mm_max_epi16" => p!("sse2.pmaxs.w", (i16x8, i16x8) -> i16x8),
        "mm_max_epu8" => p!("sse2.pmaxu.b", (i8x16, i8x16) -> i8x16),
        "mm_min_epi16" => p!("sse2.pmins.w", (i16x8, i16x8) -> i16x8),
        "mm_min_epu8" => p!("sse2.pminu.b", (i8x16, i8x16) -> i8x16),
        "mm_mul_epu32" => p!("sse2.pmulu.dq", (i32x4, i32x4) -> i64x2),
        "mm_mulhi_epi16" => p!("sse2.pmulh.w", (i8x16, i8x16) -> i8x16),
        "mm_mulhi_epu16" => p!("sse2.pmulhu.w", (i8x16, i8x16) -> i8x16),
        "mm_packs_epi16" => p!("sse2.packsswb.128", (i16x8, i16x8) -> i8x16),
        "mm_packs_epi32" => p!("sse2.packssdw.128", (i32x4, i32x4) -> i16x8),
        "mm_packus_epi16" => p!("sse2.packuswb.128", (i16x8, i16x8) -> i8x16),
        "mm_sad_epu8" => p!("sse2.psad.bw", (i8x16, i8x16) -> i64x2),
        "mm_subs_epi16" => p!("sse2.psubs.w", (i16x8, i16x8) -> i16x8),
        "mm_subs_epi8" => p!("sse2.psubs.b", (i8x16, i8x16) -> i8x16),
        "mm_subs_epu16" => p!("sse2.psubus.w", (i16x8, i16x8) -> i16x8),
        "mm_subs_epu8" => p!("sse2.psubus.b", (i8x16, i8x16) -> i8x16),

        _ => return None
    })
}
<commit_msg>Reorganise x86 intrinsic definitions.<commit_after>// Copyright 2015 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 {Intrinsic, i, f, v};
use rustc::middle::ty;

macro_rules! p {
    ($name: expr, ($($inputs: tt),*) -> $output: tt) => {
        plain!(concat!("llvm.x86.", $name), ($($inputs),*) -> $output)
    }
}

pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> {
    if !name.starts_with("mm_") { return None }

    Some(match &name["mm_".len()..] {
        "sqrt_ps" => plain!("llvm.sqrt.v4f32", (f32x4) -> f32x4),
        "sqrt_pd" => plain!("llvm.sqrt.v2f64", (f64x2) -> f64x2),

        "movemask_ps" => p!("sse.movmsk.ps", (f32x4) -> i32),
        "max_ps" => p!("sse.max.ps", (f32x4, f32x4) -> f32x4),
        "min_ps" => p!("sse.min.ps", (f32x4, f32x4) -> f32x4),
        "rsqrt_ps" => p!("sse.rsqrt.ps", (f32x4) -> f32x4),
        "rcp_ps" => p!("sse.rcp.ps", (f32x4) -> f32x4),

        "adds_epi16" => p!("sse2.padds.w", (i16x8, i16x8) -> i16x8),
        "adds_epi8" => p!("sse2.padds.b", (i8x16, i8x16) -> i8x16),
        "adds_epu16" => p!("sse2.paddus.w", (i16x8, i16x8) -> i16x8),
        "adds_epu8" => p!("sse2.paddus.b", (i8x16, i8x16) -> i8x16),
        "avg_epu16" => p!("sse2.pavg.w", (i16x8, i16x8) -> i16x8),
        "avg_epu8" => p!("sse2.pavg.b", (i8x16, i8x16) -> i8x16),
        "madd_epi16" => p!("sse2.pmadd.wd", (i16x8, i16x8) -> i32x4),
        "max_epi16" => p!("sse2.pmaxs.w", (i16x8, i16x8) -> i16x8),
        "max_epu8" => p!("sse2.pmaxu.b", (i8x16, i8x16) -> i8x16),
        "max_pd" => p!("sse2.max.pd", (f64x2, f64x2) -> f64x2),
        "min_epi16" => p!("sse2.pmins.w", (i16x8, i16x8) -> i16x8),
        "min_epu8" => p!("sse2.pminu.b", (i8x16, i8x16) -> i8x16),
        "min_pd" => p!("sse2.min.pd", (f64x2, f64x2) -> f64x2),
        "movemask_pd" => p!("sse2.movmsk.pd", (f64x2) -> i32),
        "movemask_epi8" => p!("sse2.pmovmskb.128", (i8x16) -> i32),
        "mul_epu32" => p!("sse2.pmulu.dq", (i32x4, i32x4) -> i64x2),
        "mulhi_epi16" => p!("sse2.pmulh.w", (i8x16, i8x16) -> i8x16),
        "mulhi_epu16" => p!("sse2.pmulhu.w", (i8x16, i8x16) -> i8x16),
        "packs_epi16" => p!("sse2.packsswb.128", (i16x8, i16x8) -> i8x16),
        "packs_epi32" => p!("sse2.packssdw.128", (i32x4, i32x4) -> i16x8),
        "packus_epi16" => p!("sse2.packuswb.128", (i16x8, i16x8) -> i8x16),
        "sad_epu8" => p!("sse2.psad.bw", (i8x16, i8x16) -> i64x2),
        "subs_epi16" => p!("sse2.psubs.w", (i16x8, i16x8) -> i16x8),
        "subs_epi8" => p!("sse2.psubs.b", (i8x16, i8x16) -> i8x16),
        "subs_epu16" => p!("sse2.psubus.w", (i16x8, i16x8) -> i16x8),
        "subs_epu8" => p!("sse2.psubus.b", (i8x16, i8x16) -> i8x16),

        "shuffle_epi8" => p!("ssse3.pshuf.b.128", (i8x16, i8x16) -> i8x16),
        _ => return None
    })
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * 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.
*/

use std::cell::RefCell;
use std::ops::Deref;
use std::any::Any;
use std::fs::{File};
use std::io::Error;
use std::path::Path;
use std::io::Write;

use ::akriti_core;
use akriti_core::paint::{Point, Rect};
use akriti_core::draw::{BoundingBox};
use akriti_core::props::{Directionality, Color};
use ::skia::{Surface, Paint, ImageInfo, ColorType, AlphaType, Typeface,
             Color as SkiaColor, TextEncoding, Rect as SkiaRect, Path as SkiaPath};

pub struct Canvas {
    surface: Surface,
    paint: RefCell<Paint>
}

impl Canvas {
    pub fn new(width: f32, height: f32, typeface: &Typeface) -> Canvas {
        let surface = Surface::new_raster(&ImageInfo {
            width: width.ceil() as i32,
            height: height.ceil() as i32,
            colorType: ColorType::default_8888(),
            alphaType: AlphaType::PREMUL_SK_ALPHATYPE,
        }, &None);

        let mut paint = Paint::new();
        paint.set_typeface(typeface);

        Canvas {
            surface,
            paint: RefCell::new(paint),
        }
    }

    pub fn snapshot(&self, path: &Path) -> Result<(), Error> {
        let data = self.surface.new_image_snapshot().encode();
        let mut file = File::create(path)?;

        file.write(data.get_data())?;

        Ok(())
    }
}

impl akriti_core::paint::Canvas for Canvas {
    fn draw_text(&self, top_left: &Point, bound: &BoundingBox, text: &str, color: &Color, size: f32,
                 _: &Directionality) {

        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_text_size(size);
        paint.set_text_encoding(TextEncoding::kUTF8_TextEncoding);
        paint.set_antialias(true);
        paint.set_stroke(false);

        self.surface.get_canvas().draw_text(text, top_left.x(), top_left.y()+bound.baseline_pos(),
                                            paint.deref());
    }

    fn draw_glyph(&self, top_left: &Point, _: &BoundingBox, glyph_index: u32, color: &Color,
                  size: f32, _: &Directionality) {
        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_text_size(size);
        paint.set_text_encoding(TextEncoding::kGlyphID_TextEncoding);
        paint.set_antialias(true);
        paint.set_stroke(false);

        self.surface.get_canvas().draw_blob(&[glyph_index as u16], top_left.x(), top_left.y(),
                                            paint.deref());
    }

    fn draw_rect(&self, top_left: &Point, rect: &Rect, color: &Color) {
        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_antialias(true);
        paint.set_stroke(false);

        self.surface.get_canvas().draw_rect(&SkiaRect {
            left: top_left.x(),
            top: top_left.y(),
            right: top_left.x()+rect.width(),
            bottom: top_left.y()+rect.height(),
        }, paint.deref());
    }

    fn draw_rect_outline(&self, top_left: &Point, rect: &Rect, color: &Color, stroke_width: f32) {
        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_antialias(true);
        paint.set_stroke(true);
        paint.set_stroke_width(stroke_width);

        self.surface.get_canvas().draw_rect(&SkiaRect {
            left: top_left.x(),
            top: top_left.y(),
            right: top_left.x()+rect.width(),
            bottom: top_left.y()+rect.height(),
        }, paint.deref());
    }

    fn draw_line(&self, start: &Point, end: &Point, color: &Color, stroke_width: f32) {
        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_antialias(true);
        paint.set_stroke(true);
        paint.set_stroke_width(stroke_width);

        let mut path = SkiaPath::new();
        path.move_to(start.x(), start.y());
        path.line_to(end.x(), end.y());

        self.surface.get_canvas().draw_path(&path, paint.deref());
    }

    fn as_any(&self) -> &Any {
        self
    }
}<commit_msg>Origin of glyph is at baseline<commit_after>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * 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.
*/

use std::cell::RefCell;
use std::ops::Deref;
use std::any::Any;
use std::fs::{File};
use std::io::Error;
use std::path::Path;
use std::io::Write;

use ::akriti_core;
use akriti_core::paint::{Point, Rect};
use akriti_core::draw::{BoundingBox};
use akriti_core::props::{Directionality, Color};
use ::skia::{Surface, Paint, ImageInfo, ColorType, AlphaType, Typeface,
             Color as SkiaColor, TextEncoding, Rect as SkiaRect, Path as SkiaPath};

pub struct Canvas {
    surface: Surface,
    paint: RefCell<Paint>
}

impl Canvas {
    pub fn new(width: f32, height: f32, typeface: &Typeface) -> Canvas {
        let surface = Surface::new_raster(&ImageInfo {
            width: width.ceil() as i32,
            height: height.ceil() as i32,
            colorType: ColorType::default_8888(),
            alphaType: AlphaType::PREMUL_SK_ALPHATYPE,
        }, &None);

        let mut paint = Paint::new();
        paint.set_typeface(typeface);

        Canvas {
            surface,
            paint: RefCell::new(paint),
        }
    }

    pub fn snapshot(&self, path: &Path) -> Result<(), Error> {
        let data = self.surface.new_image_snapshot().encode();
        let mut file = File::create(path)?;

        file.write(data.get_data())?;

        Ok(())
    }
}

impl akriti_core::paint::Canvas for Canvas {
    fn draw_text(&self, top_left: &Point, bound: &BoundingBox, text: &str, color: &Color, size: f32,
                 _: &Directionality) {

        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_text_size(size);
        paint.set_text_encoding(TextEncoding::kUTF8_TextEncoding);
        paint.set_antialias(true);
        paint.set_stroke(false);

        self.surface.get_canvas().draw_text(text, top_left.x(), top_left.y()+bound.baseline_pos(),
                                            paint.deref());
    }

    fn draw_glyph(&self, top_left: &Point, bounds: &BoundingBox, glyph_index: u32, color: &Color,
                  size: f32, _: &Directionality) {
        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_text_size(size);
        paint.set_text_encoding(TextEncoding::kGlyphID_TextEncoding);
        paint.set_antialias(true);
        paint.set_stroke(false);

        self.surface.get_canvas().draw_blob(&[glyph_index as u16], top_left.x(),
                                            top_left.y()+bounds.baseline_pos(), paint.deref());
    }

    fn draw_rect(&self, top_left: &Point, rect: &Rect, color: &Color) {
        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_antialias(true);
        paint.set_stroke(false);

        self.surface.get_canvas().draw_rect(&SkiaRect {
            left: top_left.x(),
            top: top_left.y(),
            right: top_left.x()+rect.width(),
            bottom: top_left.y()+rect.height(),
        }, paint.deref());
    }

    fn draw_rect_outline(&self, top_left: &Point, rect: &Rect, color: &Color, stroke_width: f32) {
        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_antialias(true);
        paint.set_stroke(true);
        paint.set_stroke_width(stroke_width);

        self.surface.get_canvas().draw_rect(&SkiaRect {
            left: top_left.x(),
            top: top_left.y(),
            right: top_left.x()+rect.width(),
            bottom: top_left.y()+rect.height(),
        }, paint.deref());
    }

    fn draw_line(&self, start: &Point, end: &Point, color: &Color, stroke_width: f32) {
        let mut paint = self.paint.borrow_mut();
        paint.set_color(&SkiaColor {
            r: color.r(),
            g: color.g(),
            b: color.b(),
            a: color.a(),
        });
        paint.set_antialias(true);
        paint.set_stroke(true);
        paint.set_stroke_width(stroke_width);

        let mut path = SkiaPath::new();
        path.move_to(start.x(), start.y());
        path.line_to(end.x(), end.y());

        self.surface.get_canvas().draw_path(&path, paint.deref());
    }

    fn as_any(&self) -> &Any {
        self
    }
}<|endoftext|>


<commit_before>use std::sync::Arc;

use base_db::SourceDatabaseExt;

use super::*;

fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: &str) {
    let (mut db, pos) = TestDB::with_position(ra_fixture_initial);
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            db.crate_def_map(krate);
        });
        assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
    db.set_file_text(pos.file_id, Arc::new(ra_fixture_change.to_string()));

    {
        let events = db.log_executed(|| {
            db.crate_def_map(krate);
        });
        assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
}

#[test]
fn typing_inside_a_function_should_not_invalidate_def_map() {
    check_def_map_is_not_recomputed(
        r"
        //- /lib.rs
        mod foo;$0

        use crate::foo::bar::Baz;

        enum E { A, B }
        use E::*;

        fn foo() -> i32 {
            1 + 1
        }

        #[cfg(never)]
        fn no() {}
        //- /foo/mod.rs
        pub mod bar;

        //- /foo/bar.rs
        pub struct Baz;
        ",
        r"
        mod foo;

        use crate::foo::bar::Baz;

        enum E { A, B }
        use E::*;

        fn foo() -> i32 { 92 }

        #[cfg(never)]
        fn no() {}
        ",
    );
}

#[test]
fn typing_inside_a_macro_should_not_invalidate_def_map() {
    let (mut db, pos) = TestDB::with_position(
        r"
        //- /lib.rs
        macro_rules! m {
            ($ident:ident) => {
                fn f() {
                    $ident + $ident;
                };
            }
        }
        mod foo;

        //- /foo/mod.rs
        pub mod bar;

        //- /foo/bar.rs
        $0
        m!(X);
        ",
    );
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 1);
        });
        assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
    db.set_file_text(pos.file_id, Arc::new("m!(Y);".to_string()));

    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 1);
        });
        assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
}

#[test]
fn typing_inside_a_function_doe_should_not_invalidate_expansions() {
    let (mut db, pos) = TestDB::with_position(
        r#"
//- /lib.rs
macro_rules! m {
    ($ident:ident) => {
        fn $ident() { };
    }
}
mod foo;

//- /foo/mod.rs
pub mod bar;

//- /foo/bar.rs
m!(X);
fn quux() { 1$0 }
m!(Y);
m!(Z);
"#,
    );
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 4);
        });
        let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
        assert_eq!(n_recalculated_item_trees, 6);
    }

    let new_text = r#"
m!(X);
fn quux() { 92 }
m!(Y);
m!(Z);
"#;
    db.set_file_text(pos.file_id, Arc::new(new_text.to_string()));

    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 4);
        });
        let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
        assert_eq!(n_recalculated_item_trees, 1);
    }
}
<commit_msg>Update crates/hir_def/src/nameres/tests/incremental.rs<commit_after>use std::sync::Arc;

use base_db::SourceDatabaseExt;

use super::*;

fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: &str) {
    let (mut db, pos) = TestDB::with_position(ra_fixture_initial);
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            db.crate_def_map(krate);
        });
        assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
    db.set_file_text(pos.file_id, Arc::new(ra_fixture_change.to_string()));

    {
        let events = db.log_executed(|| {
            db.crate_def_map(krate);
        });
        assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
}

#[test]
fn typing_inside_a_function_should_not_invalidate_def_map() {
    check_def_map_is_not_recomputed(
        r"
        //- /lib.rs
        mod foo;$0

        use crate::foo::bar::Baz;

        enum E { A, B }
        use E::*;

        fn foo() -> i32 {
            1 + 1
        }

        #[cfg(never)]
        fn no() {}
        //- /foo/mod.rs
        pub mod bar;

        //- /foo/bar.rs
        pub struct Baz;
        ",
        r"
        mod foo;

        use crate::foo::bar::Baz;

        enum E { A, B }
        use E::*;

        fn foo() -> i32 { 92 }

        #[cfg(never)]
        fn no() {}
        ",
    );
}

#[test]
fn typing_inside_a_macro_should_not_invalidate_def_map() {
    let (mut db, pos) = TestDB::with_position(
        r"
        //- /lib.rs
        macro_rules! m {
            ($ident:ident) => {
                fn f() {
                    $ident + $ident;
                };
            }
        }
        mod foo;

        //- /foo/mod.rs
        pub mod bar;

        //- /foo/bar.rs
        $0
        m!(X);
        ",
    );
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 1);
        });
        assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
    db.set_file_text(pos.file_id, Arc::new("m!(Y);".to_string()));

    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 1);
        });
        assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
}

#[test]
fn typing_inside_a_function_should_not_invalidate_expansions() {
    let (mut db, pos) = TestDB::with_position(
        r#"
//- /lib.rs
macro_rules! m {
    ($ident:ident) => {
        fn $ident() { };
    }
}
mod foo;

//- /foo/mod.rs
pub mod bar;

//- /foo/bar.rs
m!(X);
fn quux() { 1$0 }
m!(Y);
m!(Z);
"#,
    );
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 4);
        });
        let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
        assert_eq!(n_recalculated_item_trees, 6);
    }

    let new_text = r#"
m!(X);
fn quux() { 92 }
m!(Y);
m!(Z);
"#;
    db.set_file_text(pos.file_id, Arc::new(new_text.to_string()));

    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 4);
        });
        let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
        assert_eq!(n_recalculated_item_trees, 1);
    }
}
<|endoftext|>