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

// This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results
// in a runtime panic.

#![feature(never_type)]

use std::{mem, panic};

struct Foo {
    x: u8,
    y: !,
}

enum Bar {}

fn main() {
    unsafe {
        assert_eq!(
            panic::catch_unwind(|| {
                mem::uninitialized::<!>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type ! using mem::uninitialized"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::zeroed::<!>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type ! using mem::zeroed"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::uninitialized::<Foo>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type Foo using mem::uninitialized"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::zeroed::<Foo>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type Foo using mem::zeroed"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::uninitialized::<Bar>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type Bar using mem::uninitialized"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::zeroed::<Bar>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type Bar using mem::zeroed"
            })),
            Some(true)
        );
    }
}
<commit_msg>the test requires unwinding so we don't run it on the wasm32-bare target<commit_after>// Copyright 2018 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.

// ignore-wasm32-bare always compiled as panic=abort right now and this requires unwinding
// This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results
// in a runtime panic.

#![feature(never_type)]

use std::{mem, panic};

struct Foo {
    x: u8,
    y: !,
}

enum Bar {}

fn main() {
    unsafe {
        assert_eq!(
            panic::catch_unwind(|| {
                mem::uninitialized::<!>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type ! using mem::uninitialized"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::zeroed::<!>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type ! using mem::zeroed"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::uninitialized::<Foo>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type Foo using mem::uninitialized"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::zeroed::<Foo>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type Foo using mem::zeroed"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::uninitialized::<Bar>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type Bar using mem::uninitialized"
            })),
            Some(true)
        );

        assert_eq!(
            panic::catch_unwind(|| {
                mem::zeroed::<Bar>()
            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
                s == "Attempted to instantiate uninhabited type Bar using mem::zeroed"
            })),
            Some(true)
        );
    }
}
<|endoftext|>


<commit_before>use std::io;

use futures::stream::Stream;
use futures::{Future, Task, Poll};
use futures_io::{Ready, IoFuture};

use event_loop::{IoSource, LoopHandle};

/// A concrete implementation of a stream of readiness notifications for I/O
/// objects that originates from an event loop.
///
/// Created by the `ReadinessStream::new` method, each `ReadinessStream` is
/// associated with a specific event loop and source of events that will be
/// registered with an event loop.
///
/// Currently readiness streams have "edge" semantics. That is, if a stream
/// receives a readable notification it will not receive another readable
/// notification until all bytes have been read from the stream.
///
/// Note that the precise semantics of when notifications are received will
/// likely be configurable in the future.
pub struct ReadinessStream {
    io_token: usize,
    loop_handle: LoopHandle,
    source: IoSource,
}

impl ReadinessStream {
    /// Creates a new readiness stream associated with the provided
    /// `loop_handle` and for the given `source`.
    ///
    /// This method returns a future which will resolve to the readiness stream
    /// when it's ready.
    pub fn new(loop_handle: LoopHandle, source: IoSource)
               -> Box<IoFuture<ReadinessStream>> {
        loop_handle.add_source(source.clone()).map(|token| {
            ReadinessStream {
                io_token: token,
                source: source,
                loop_handle: loop_handle,
            }
        }).boxed()
    }
}

impl Stream for ReadinessStream {
    type Item = Ready;
    type Error = io::Error;

    fn poll(&mut self, _task: &mut Task) -> Poll<Option<Ready>, io::Error> {
        match self.source.take_readiness() {
            None => Poll::NotReady,
            Some(r) => Poll::Ok(Some(r)),
        }
    }

    fn schedule(&mut self, task: &mut Task) {
        self.loop_handle.schedule(self.io_token, task)
    }
}

impl Drop for ReadinessStream {
    fn drop(&mut self) {
        self.loop_handle.drop_source(self.io_token)
    }
}
<commit_msg>Remove extraneous allocation on ReadinessStream::new<commit_after>use std::io;

use futures::stream::Stream;
use futures::{Future, Task, Poll};
use futures_io::{Ready};

use event_loop::{IoSource, LoopHandle, AddSource};

/// A concrete implementation of a stream of readiness notifications for I/O
/// objects that originates from an event loop.
///
/// Created by the `ReadinessStream::new` method, each `ReadinessStream` is
/// associated with a specific event loop and source of events that will be
/// registered with an event loop.
///
/// Currently readiness streams have "edge" semantics. That is, if a stream
/// receives a readable notification it will not receive another readable
/// notification until all bytes have been read from the stream.
///
/// Note that the precise semantics of when notifications are received will
/// likely be configurable in the future.
pub struct ReadinessStream {
    io_token: usize,
    loop_handle: LoopHandle,
    source: IoSource,
}

pub struct ReadinessStreamNew {
    inner: AddSource,
    handle: Option<LoopHandle>,
    source: Option<IoSource>,
}

impl ReadinessStream {
    /// Creates a new readiness stream associated with the provided
    /// `loop_handle` and for the given `source`.
    ///
    /// This method returns a future which will resolve to the readiness stream
    /// when it's ready.
    pub fn new(loop_handle: LoopHandle, source: IoSource)
               -> ReadinessStreamNew {
        ReadinessStreamNew {
            inner: loop_handle.add_source(source.clone()),
            source: Some(source),
            handle: Some(loop_handle),
        }
    }
}

impl Future for ReadinessStreamNew {
    type Item = ReadinessStream;
    type Error = io::Error;

    fn poll(&mut self, task: &mut Task) -> Poll<ReadinessStream, io::Error> {
        self.inner.poll(task).map(|token| {
            ReadinessStream {
                io_token: token,
                source: self.source.take().unwrap(),
                loop_handle: self.handle.take().unwrap(),
            }
        })
    }

    fn schedule(&mut self, task: &mut Task) {
        self.inner.schedule(task)
    }
}

impl Stream for ReadinessStream {
    type Item = Ready;
    type Error = io::Error;

    fn poll(&mut self, _task: &mut Task) -> Poll<Option<Ready>, io::Error> {
        match self.source.take_readiness() {
            None => Poll::NotReady,
            Some(r) => Poll::Ok(Some(r)),
        }
    }

    fn schedule(&mut self, task: &mut Task) {
        self.loop_handle.schedule(self.io_token, task)
    }
}

impl Drop for ReadinessStream {
    fn drop(&mut self) {
        self.loop_handle.drop_source(self.io_token)
    }
}
<|endoftext|>


<commit_before>use super::*;

#[test]
fn api_structure() {
	// is the api structured as we want it to be?

	let client = Client::new("my_api_key".to_string());

	let response = client.api().info().get_fullentry();

	println!("request:    {:#?}",  response);

	panic!();
}
<commit_msg>dactivate tests<commit_after>use super::*;

#[test]
fn api_structure() {
	// is the api structured as we want it to be?

	let client = Client::new("my_api_key".to_string());

}
<|endoftext|>


<commit_before>extern mod index;

use index::Index;

#[test]
fn test_or_operator() {
	let a = Index::new( ~[1, 2, 3] );
	let b = Index::new( ~[2, 3, 4] );
	let c = a + b;
	assert_eq!(c.to_vec(), ~[1, 2, 3, 4]);
}

#[test]
fn test_and_operator() {
	let a = Index::new( ~[1, 2, 3] );
	let b = Index::new( ~[2, 3, 4] );
	let c = a * b;
	assert_eq!(c.to_vec(), ~[2, 3]);
}

#[test]
fn test_except_operator() {
	let a = Index::new( ~[1, 2, 3] );
	let b = Index::new( ~[2, 3, 4] );
	let c = a - b;
	assert_eq!(c.to_vec(), ~[1]);
}

#[test]
fn test_advanced() {
	let a = Index::new( ~[1, 5, 8] );
	let b = Index::new( ~[0, 1, 5] );
	let c = Index::new( ~[0, 1, 5, 8] );
	let d = a + b - c;
	assert_eq!(d.to_vec(), ~[]);
}

#[test]
fn test_index_of_Index() {
	let a = Index::new( ~[1, 5, 10] );
	let b = a.index_of(5);
	assert_eq!(b, ::index::Found(1));
}

#[test]
fn test2_index_of_Index() {
	let a = Index::new( ~[1, 2, 10] );
	let b = a.index_of(0);
	assert_eq!(b, ::index::FoundLarger(0));
}

#[test]
fn test_strs() {
	let a = Index::new( ~[~"apes", ~"banana", ~"monkey"] );
	let b = Index::new( ~[~"banana", ~"monkey", ~"snakes"] );
	let c = a + b;
	assert_eq!(c.to_vec(),
		~[~"apes", ~"banana", ~"monkey", ~"snakes"]);
}

#[test]
fn test_example_2() {
	let a = Index::new( ~[1, 2, 3] );
	let b = Index::new( ~[2, 3, 4] );
	let c = Index::new( ~[1, 4] );
	let d = a * (b - c);
	assert_eq!(d.to_vec(), ~[2, 3]);
}

#[test]
fn test_new_check_order() {
	assert!(!Index::check_order( &~[1, 3, 2] ));
}

#[test]
fn test_new_check_order_empty() {
	let a: ~[int] = ~[];
	assert!(Index::check_order(&a));
}

#[test]
fn test_new_check_order_sort_retry() {
	let mut a = ~[1, 3, 2];
	let ordered = Index::check_order(&a);
	assert!(!ordered);
	if !ordered {
		a.swap(1, 2);
	}

	let ordered = Index::check_order(&a);
	assert!(ordered);
}

<commit_msg>Added unit test for ownership.<commit_after>extern mod index;

use index::Index;

#[test]
fn test_or_operator() {
	let a = Index::new( ~[1, 2, 3] );
	let b = Index::new( ~[2, 3, 4] );
	let c = a + b;
	assert_eq!(c.to_vec(), ~[1, 2, 3, 4]);
}

#[test]
fn test_and_operator() {
	let a = Index::new( ~[1, 2, 3] );
	let b = Index::new( ~[2, 3, 4] );
	let c = a * b;
	assert_eq!(c.to_vec(), ~[2, 3]);
}

#[test]
fn test_except_operator() {
	let a = Index::new( ~[1, 2, 3] );
	let b = Index::new( ~[2, 3, 4] );
	let c = a - b;
	assert_eq!(c.to_vec(), ~[1]);
}

#[test]
fn test_advanced() {
	let a = Index::new( ~[1, 5, 8] );
	let b = Index::new( ~[0, 1, 5] );
	let c = Index::new( ~[0, 1, 5, 8] );
	let d = a + b - c;
	assert_eq!(d.to_vec(), ~[]);
}

#[test]
fn test_index_of_Index() {
	let a = Index::new( ~[1, 5, 10] );
	let b = a.index_of(5);
	assert_eq!(b, ::index::Found(1));
}

#[test]
fn test2_index_of_Index() {
	let a = Index::new( ~[1, 2, 10] );
	let b = a.index_of(0);
	assert_eq!(b, ::index::FoundLarger(0));
}

#[test]
fn test_strs() {
	let a = Index::new( ~[~"apes", ~"banana", ~"monkey"] );
	let b = Index::new( ~[~"banana", ~"monkey", ~"snakes"] );
	let c = a + b;
	assert_eq!(c.to_vec(),
		~[~"apes", ~"banana", ~"monkey", ~"snakes"]);
}

#[test]
fn test_example_2() {
	let a = Index::new( ~[1, 2, 3] );
	let b = Index::new( ~[2, 3, 4] );
	let c = Index::new( ~[1, 4] );
	let d = a * (b - c);
	assert_eq!(d.to_vec(), ~[2, 3]);
}

#[test]
fn test_new_check_order() {
	assert!(!Index::check_order( &~[1, 3, 2] ));
}

#[test]
fn test_new_check_order_empty() {
	let a: ~[int] = ~[];
	assert!(Index::check_order(&a));
}

#[test]
fn test_new_check_order_sort_retry() {
	let mut a = ~[1, 3, 2];
	let ordered = Index::check_order(&a);
	assert!(!ordered);
	if !ordered {
		a.swap(1, 2);
	}

	let ordered = Index::check_order(&a);
	assert!(ordered);
}

#[test]
fn test_ownership() {
	let a = Index::new( ~[1, 2, 3] );
	let ref b = a;
	assert_eq!(a.to_vec(), ~[1, 2, 3]);
	assert_eq!(b.to_vec(), ~[1, 2, 3]);
}

<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Regular language
//!
//! This provides a data structure representing a regular language. This is a more generalised form of a regular
//! expression (it supports symbol types other than simple strings). A regular language using the `u8` symbol forms
//! a simple regular expression.
//!

use std::slice::*;

///
/// A phrase iterator can be used to return the symbols in a phrase one at a time
///
trait PhraseIterator<'a, Symbol> {
    fn next_symbol(&mut self) -> Option<&Symbol>;
}

///
/// Phrases are sequences of symbols, matched in order
///
trait Phrase<Symbol> {
    ///
    /// Retrieves an iterator that can be used to read the symbols for this phrase
    ///
    fn get_symbols<'a>(&self) -> PhraseIterator<'a, Symbol>;
}

impl<Symbol> Phrase<Symbol> for Vec<Symbol> {
    #[inline]
    fn get_symbols<'a>(&self) -> PhraseIterator<'a, Symbol> {
        self.iter()
    }
}

impl<'a, Symbol> PhraseIterator<'a, Symbol> for Iter<'a, Symbol> {
    #[inline]
    fn next_symbol(&mut self) -> Option<&Symbol> {
        self.next()
    }
}

/*
impl<Symbol> Phrase<Symbol> for [Symbol] {
    #[inline]
    fn get_symbols(&self) -> Iterator<Item=Symbol> {
        self.iter()
    }
}
*/<commit_msg>Fix phrase typing<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Regular language
//!
//! This provides a data structure representing a regular language. This is a more generalised form of a regular
//! expression (it supports symbol types other than simple strings). A regular language using the `u8` symbol forms
//! a simple regular expression.
//!

use std::slice::*;

///
/// A phrase iterator can be used to return the symbols in a phrase one at a time
///
pub trait PhraseIterator<Symbol> {
    fn next_symbol(&mut self) -> Option<&Symbol>;
}

///
/// Phrases are sequences of symbols, matched in order
///
pub trait Phrase<Symbol> {
    type PhraseIterator: PhraseIterator<Symbol>;

    ///
    /// Retrieves an iterator that can be used to read the symbols for this phrase
    ///
    fn get_symbols(self) -> Self::PhraseIterator;
}

impl<'a, Symbol> Phrase<Symbol> for &'a Vec<Symbol> {
    type PhraseIterator = Iter<'a, Symbol>;

    #[inline]
    fn get_symbols(self) -> Self::PhraseIterator {
        self.iter()
    }
}

impl<'a, Symbol> PhraseIterator<Symbol> for Iter<'a, Symbol> {
    #[inline]
    fn next_symbol(&mut self) -> Option<&Symbol> {
        self.next()
    }
}

impl<'a, Symbol> Phrase<Symbol> for &'a [Symbol] {
    type PhraseIterator = Iter<'a, Symbol>;

    #[inline]
    fn get_symbols(self) -> Self::PhraseIterator {
        self.iter()
    }
}
<|endoftext|>


<commit_before>// tokenizer
#![allow(non_camel_case_types)]

use std::cmp;
use std::sync::Mutex;

lazy_static! {
    static ref SYMBOLS: Mutex<Vec<Symbol>> = Mutex::new(Vec::new());
}

fn init_symbols() {
    let mut symbols = SYMBOLS.lock().unwrap();

    symbols.push(Symbol { name: "else", ty: TokenType::ELSE });
    symbols.push(Symbol { name: "for", ty: TokenType::FOR });
    symbols.push(Symbol { name: "if", ty: TokenType::IF });
    symbols.push(Symbol { name: "int", ty: TokenType::INT });
    symbols.push(Symbol { name: "return", ty: TokenType::RETURN });
    symbols.push(Symbol { name: "&&", ty: TokenType::LOGAND });
    symbols.push(Symbol { name: "||", ty: TokenType::LOGOR });
}

struct Symbol {
    name: &'static str,
    ty: TokenType,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TokenType {
    NUM,
    ADD,
    SUB,
    MUL,
    DIV,
    EQ,
    LT,
    GT,
    BRA,
    KET,
    C_BRA,
    C_KET,
    IDENT,
    INT,
    IF,
    FOR,
    ELSE,
    LOGOR,
    LOGAND,
    RETURN,
    COMMA,
    SEMI_COLON,
    EOF,
}

#[derive(Debug)]
pub struct Token {
    pub ty: TokenType,
    pub val: i32,
    pub name: String,
    pub input: String,
}

fn scan(p: &String) -> Vec<Token> {
    let mut tokens = Vec::new();
    let char_bytes = p.as_bytes();
    let mut idx = 0;
    'outer: while idx < char_bytes.len() {
        let c: char = char::from(char_bytes[idx]);
        if c.is_whitespace() {
            idx += 1;
            continue;
        }
        if "+-*/;=(),{}<>".contains(c) {
            let ty = match c {
                '+' => TokenType::ADD,
                '-' => TokenType::SUB,
                '*' => TokenType::MUL,
                '/' => TokenType::DIV,
                ';' => TokenType::SEMI_COLON,
                '=' => TokenType::EQ,
                '<' => TokenType::LT,
                '>' => TokenType::GT,
                '(' => TokenType::BRA,
                ')' => TokenType::KET,
                '{' => TokenType::C_BRA,
                '}' => TokenType::C_KET,
                ',' => TokenType::COMMA,
                _ => panic!(format!("unknown {}", c)),
            };
            let tok = Token {
                ty: ty,
                val: 0,
                name: String::new(),
                input: format!("{}", c),
            };

            tokens.push(tok);

            idx += 1;
            continue;
        }

        // Multi-letter token
        match SYMBOLS.lock() {
            Ok(symbols) => {
                for s in symbols.iter() {
                    let bs = &char_bytes[idx..cmp::min(idx+s.name.len(), char_bytes.len())];
                    if s.name.as_bytes() != bs {
                        continue;
                    }

                    tokens.push(Token{
                        ty: s.ty,
                        val: 0,
                        name: String::from(s.name),
                        input: String::from(s.name),
                    });

                    idx += s.name.len();
                    continue 'outer;
                }
            }
            Err(_) => {
                panic!();
            }
        }

        // Identifier
        if c.is_alphabetic() || c == '_' {
            let mut s = String::new();
            s.push(c);
            idx += 1;
            while idx < char_bytes.len() {
                let d = char::from(char_bytes[idx]);
                if d.is_alphabetic() || d.is_digit(10) || d == '_' {
                    s.push(d);
                    idx += 1;
                } else {
                    break;
                }
            }

            let tok = Token {
                ty: TokenType::IDENT,
                val: 0,
                name: s.clone(),
                input: s.clone(),
            };

            tokens.push(tok);
            continue;
        }

        // Number
        if c.is_digit(10) {
            let mut s = String::new();
            s.push(c);
            idx += 1;
            while idx < char_bytes.len() {
                let d = char::from(char_bytes[idx]);
                if d.is_digit(10) {
                    s.push(d);
                    idx += 1;
                } else {
                    break;
                }
            }
            let tok = Token {
                ty: TokenType::NUM,
                val: i32::from_str_radix(&s, 10).unwrap(),
                name: String::new(),
                input: s,
            };

            tokens.push(tok);
            continue;
        }

        panic!(format!("cannot tokenize: {}", c));
    }

    let tok = Token {
        ty: TokenType::EOF,
        val: 0,
        name: String::new(),
        input: String::new(),
    };
    tokens.push(tok);

    return tokens;
}

pub fn tokenize(p: &String) -> Vec<Token> {
    init_symbols();
    return scan(p);
}
<commit_msg>Simplify.<commit_after>// tokenizer
#![allow(non_camel_case_types)]

use std::cmp;
use std::sync::Mutex;

lazy_static! {
    static ref SYMBOLS: Mutex<Vec<Symbol>> = Mutex::new(Vec::new());
}

fn init_symbols() {
    let mut symbols = SYMBOLS.lock().unwrap();

    symbols.push(Symbol { name: "else", ty: TokenType::ELSE });
    symbols.push(Symbol { name: "for", ty: TokenType::FOR });
    symbols.push(Symbol { name: "if", ty: TokenType::IF });
    symbols.push(Symbol { name: "int", ty: TokenType::INT });
    symbols.push(Symbol { name: "return", ty: TokenType::RETURN });
    symbols.push(Symbol { name: "&&", ty: TokenType::LOGAND });
    symbols.push(Symbol { name: "||", ty: TokenType::LOGOR });
}

struct Symbol {
    name: &'static str,
    ty: TokenType,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TokenType {
    NUM,
    ADD,
    SUB,
    MUL,
    DIV,
    EQ,
    LT,
    GT,
    BRA,
    KET,
    C_BRA,
    C_KET,
    IDENT,
    INT,
    IF,
    FOR,
    ELSE,
    LOGOR,
    LOGAND,
    RETURN,
    COMMA,
    SEMI_COLON,
    EOF,
}

#[derive(Debug)]
pub struct Token {
    pub ty: TokenType,
    pub val: i32,
    pub name: String,
    pub input: String,
}

pub fn tokenize(p: &String) -> Vec<Token> {
    init_symbols();
    let mut tokens = Vec::new();
    let char_bytes = p.as_bytes();
    let mut idx = 0;
    'outer: while idx < char_bytes.len() {
        let c: char = char::from(char_bytes[idx]);
        if c.is_whitespace() {
            idx += 1;
            continue;
        }
        if "+-*/;=(),{}<>".contains(c) {
            let ty = match c {
                '+' => TokenType::ADD,
                '-' => TokenType::SUB,
                '*' => TokenType::MUL,
                '/' => TokenType::DIV,
                ';' => TokenType::SEMI_COLON,
                '=' => TokenType::EQ,
                '<' => TokenType::LT,
                '>' => TokenType::GT,
                '(' => TokenType::BRA,
                ')' => TokenType::KET,
                '{' => TokenType::C_BRA,
                '}' => TokenType::C_KET,
                ',' => TokenType::COMMA,
                _ => panic!(format!("unknown {}", c)),
            };
            let tok = Token {
                ty: ty,
                val: 0,
                name: String::new(),
                input: format!("{}", c),
            };

            tokens.push(tok);

            idx += 1;
            continue;
        }

        // Multi-letter token
        match SYMBOLS.lock() {
            Ok(symbols) => {
                for s in symbols.iter() {
                    let bs = &char_bytes[idx..cmp::min(idx+s.name.len(), char_bytes.len())];
                    if s.name.as_bytes() != bs {
                        continue;
                    }

                    tokens.push(Token{
                        ty: s.ty,
                        val: 0,
                        name: String::from(s.name),
                        input: String::from(s.name),
                    });

                    idx += s.name.len();
                    continue 'outer;
                }
            }
            Err(_) => {
                panic!();
            }
        }

        // Identifier
        if c.is_alphabetic() || c == '_' {
            let mut s = String::new();
            s.push(c);
            idx += 1;
            while idx < char_bytes.len() {
                let d = char::from(char_bytes[idx]);
                if d.is_alphabetic() || d.is_digit(10) || d == '_' {
                    s.push(d);
                    idx += 1;
                } else {
                    break;
                }
            }

            let tok = Token {
                ty: TokenType::IDENT,
                val: 0,
                name: s.clone(),
                input: s.clone(),
            };

            tokens.push(tok);
            continue;
        }

        // Number
        if c.is_digit(10) {
            let mut s = String::new();
            s.push(c);
            idx += 1;
            while idx < char_bytes.len() {
                let d = char::from(char_bytes[idx]);
                if d.is_digit(10) {
                    s.push(d);
                    idx += 1;
                } else {
                    break;
                }
            }
            let tok = Token {
                ty: TokenType::NUM,
                val: i32::from_str_radix(&s, 10).unwrap(),
                name: String::new(),
                input: s,
            };

            tokens.push(tok);
            continue;
        }

        panic!(format!("cannot tokenize: {}", c));
    }

    let tok = Token {
        ty: TokenType::EOF,
        val: 0,
        name: String::new(),
        input: String::new(),
    };
    tokens.push(tok);

    return tokens;
}

<|endoftext|>


<commit_before>use rustc::lint::*;
use syntax::ast;
use syntax::ast::*;
use syntax::ast_util::{is_comparison_binop, binop_to_string};
use syntax::ptr::P;
use rustc::middle::ty;
use syntax::codemap::ExpnInfo;

use utils::{in_macro, snippet, span_lint, span_help_and_lint, in_external_macro};

/// Handles all the linting of funky types
#[allow(missing_copy_implementations)]
pub struct TypePass;

declare_lint!(pub BOX_VEC, Warn,
              "usage of `Box<Vec<T>>`, vector elements are already on the heap");
declare_lint!(pub LINKEDLIST, Warn,
              "usage of LinkedList, usually a vector is faster, or a more specialized data \
               structure like a RingBuf");

/// Matches a type with a provided string, and returns its type parameters if successful
pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> {
    match ty.node {
        TyPath(_, Path {segments: ref seg, ..}) => {
            // So ast::Path isn't the full path, just the tokens that were provided.
            // I could muck around with the maps and find the full path
            // however the more efficient way is to simply reverse the iterators and zip them
            // which will compare them in reverse until one of them runs out of segments
            if seg.iter().rev().zip(segments.iter().rev()).all(|(a,b)| a.identifier.name == b) {
                match seg[..].last() {
                    Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => {
                        Some(&a.types[..])
                    }
                    _ => None
                }
            } else {
                None
            }
        },
        _ => None
    }
}

#[allow(unused_imports)]
impl LintPass for TypePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOX_VEC, LINKEDLIST)
    }

    fn check_ty(&mut self, cx: &Context, ty: &ast::Ty) {
        {
            // In case stuff gets moved around
            use std::boxed::Box;
            use std::vec::Vec;
        }
        match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.first())
          .and_then(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"]))
          .map(|_| {
            span_help_and_lint(cx, BOX_VEC, ty.span,
                              "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?",
                              "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation");
          });
        {
            // In case stuff gets moved around
            use collections::linked_list::LinkedList as DL1;
            use std::collections::linked_list::LinkedList as DL2;
        }
        let dlists = [vec!["std","collections","linked_list","LinkedList"],
                      vec!["collections","linked_list","LinkedList"]];
        for path in &dlists {
            if match_ty_unwrap(ty, &path[..]).is_some() {
                span_help_and_lint(cx, LINKEDLIST, ty.span,
                                   "I see you're using a LinkedList! Perhaps you meant some other data structure?",
                                   "a RingBuf might work");
                return;
            }
        }
    }
}

#[allow(missing_copy_implementations)]
pub struct LetPass;

declare_lint!(pub LET_UNIT_VALUE, Warn,
              "creating a let binding to a value of unit type, which usually can't be used afterwards");

fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) {
    if in_macro(cx, info) { return; }
    if let DeclLocal(ref local) = decl.node {
        let bindtype = &cx.tcx.pat_ty(&*local.pat).sty;
        if *bindtype == ty::TyTuple(vec![]) {
            span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
                "this let-binding has unit value. Consider omitting `let {} =`",
                snippet(cx, local.pat.span, "..")));
        }
    }
}

impl LintPass for LetPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(LET_UNIT_VALUE)
    }

    fn check_decl(&mut self, cx: &Context, decl: &Decl) {
        cx.sess().codemap().with_expn_info(
            decl.span.expn_id,
            |info| check_let_unit(cx, decl, info));
    }
}

declare_lint!(pub UNIT_CMP, Warn,
              "comparing unit values (which is always `true` or `false`, respectively)");

#[allow(missing_copy_implementations)]
pub struct UnitCmp;

impl LintPass for UnitCmp {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_CMP)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, _) = expr.node {
            let op = cmp.node;
            let sty = &cx.tcx.expr_ty(left).sty;
            if *sty == ty::TyTuple(vec![]) && is_comparison_binop(op) {
                let result = match op {
                    BiEq | BiLe | BiGe => "true",
                    _ => "false"
                };
                span_lint(cx, UNIT_CMP, expr.span, &format!(
                    "{}-comparison of unit values detected. This will always be {}",
                    binop_to_string(op), result));
            }
        }
    }
}

pub struct CastPass;

declare_lint!(pub CAST_PRECISION_LOSS, Allow,
              "casts that cause loss of precision, e.g `x as f32` where `x: u64`");
declare_lint!(pub CAST_SIGN_LOSS, Allow,
              "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`");
declare_lint!(pub CAST_POSSIBLE_OVERFLOW, Allow,
              "casts that may cause overflow, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`");

impl LintPass for CastPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(CAST_PRECISION_LOSS,
                    CAST_SIGN_LOSS,
                    CAST_POSSIBLE_OVERFLOW)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprCast(ref ex, _) = expr.node {
            let (cast_from, cast_to) = (cx.tcx.expr_ty(&*ex), cx.tcx.expr_ty(expr));
            if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
                match (cast_from.is_integral(), cast_to.is_integral()) {
                    (true, false)  => {
                        match (&cast_from.sty, &cast_to.sty) {
                            (&ty::TyInt(i), &ty::TyFloat(f)) => {
                                match (i, f) {
                                    (ast::TyI32, ast::TyF32) |
                                    (ast::TyI64, ast::TyF32) |
                                    (ast::TyI64, ast::TyF64) => {
                                        span_lint(cx, CAST_PRECISION_LOSS, expr.span,
                                                  &format!("converting from {} to {}, which causes a loss of precision",
                                                           i, f));
                                    },
                                    _ => ()
                                }
                            }
                            (&ty::TyUint(u), &ty::TyFloat(f)) => {
                                match (u, f) {
                                    (ast::TyU32, ast::TyF32) |
                                    (ast::TyU64, ast::TyF32) |
                                    (ast::TyU64, ast::TyF64) => {
                                        span_lint(cx, CAST_PRECISION_LOSS, expr.span,
                                                  &format!("converting from {} to {}, which causes a loss of precision",
                                                           u, f));
                                    },
                                    _ => ()
                                }
                            },
                            _ => ()
                        }
                    },
                    (false, true) => {
                        span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span,
                                  &format!("the contents of a {} may overflow a {}", cast_from, cast_to));
                        if !cast_to.is_signed() {
                            span_lint(cx, CAST_SIGN_LOSS, expr.span,
                                      &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to));
                        }
                    },
                    (true, true) => {
                        match (&cast_from.sty, &cast_to.sty) {
                            (&ty::TyInt(i1), &ty::TyInt(i2)) => {
                                match (i1, i2) {
                                    (ast::TyI64, ast::TyI32) |
                                    (ast::TyI64, ast::TyI16) |
                                    (ast::TyI64, ast::TyI8)  |
                                    (ast::TyI32, ast::TyI16) |
                                    (ast::TyI32, ast::TyI8)  |
                                    (ast::TyI16, ast::TyI8) =>
                                        span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span,
                                                  &format!("the contents of a {} may overflow a {}", i1, i2)),
                                    _ => ()
                                }
                            },
                            (&ty::TyInt(i), &ty::TyUint(u)) => {
                                span_lint(cx, CAST_SIGN_LOSS, expr.span,
                                          &format!("casting from {} to {} loses the sign of the value", i, u));
                                match (i, u) {
                                    (ast::TyI64, ast::TyU32) |
                                    (ast::TyI64, ast::TyU16) |
                                    (ast::TyI64, ast::TyU8)  |
                                    (ast::TyI32, ast::TyU16) |
                                    (ast::TyI32, ast::TyU8)  |
                                    (ast::TyI16, ast::TyU8) =>
                                        span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span,
                                                  &format!("the contents of a {} may overflow a {}", i, u)),
                                    _ => ()
                                }
                            },
                            (&ty::TyUint(u), &ty::TyInt(i)) => {
                                match (u, i) {
                                    (ast::TyU64, ast::TyI32) |
                                    (ast::TyU64, ast::TyI64) |
                                    (ast::TyU64, ast::TyI16) |
                                    (ast::TyU64, ast::TyI8)  |
                                    (ast::TyU32, ast::TyI32) |
                                    (ast::TyU32, ast::TyI16) |
                                    (ast::TyU32, ast::TyI8)  |
                                    (ast::TyU16, ast::TyI16) |
                                    (ast::TyU16, ast::TyI8)  |
                                    (ast::TyU8, ast::TyI8) =>
                                        span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span,
                                                  &format!("the contents of a {} may overflow a {}", u, i)),
                                    _ => ()
                                }
                            },
                            (&ty::TyUint(u1), &ty::TyUint(u2)) => {
                                match (u1, u2) {
                                    (ast::TyU64, ast::TyU32) |
                                    (ast::TyU64, ast::TyU16) |
                                    (ast::TyU64, ast::TyU8)  |
                                    (ast::TyU32, ast::TyU16) |
                                    (ast::TyU32, ast::TyU8)  |
                                    (ast::TyU16, ast::TyU8) =>
                                        span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span,
                                                  &format!("the contents of a {} may overflow a {}", u1, u2)),
                                    _ => ()
                                }
                            },
                            _ => ()
                        }
                    }
                    (false, false) => {
                        if let (&ty::TyFloat(ast::TyF64),
                                &ty::TyFloat(ast::TyF32)) = (&cast_from.sty, &cast_to.sty) {
                            span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, "the contents of a f64 may overflow a f32");
                        }
                    }
                }
            }
        }
    }
}
<commit_msg>Refactored the CastPass lints.<commit_after>use rustc::lint::*;
use syntax::ast;
use syntax::ast::*;
use syntax::ast_util::{is_comparison_binop, binop_to_string};
use syntax::ptr::P;
use rustc::middle::ty;
use syntax::codemap::ExpnInfo;

use utils::{in_macro, snippet, span_lint, span_help_and_lint, in_external_macro};

/// Handles all the linting of funky types
#[allow(missing_copy_implementations)]
pub struct TypePass;

declare_lint!(pub BOX_VEC, Warn,
              "usage of `Box<Vec<T>>`, vector elements are already on the heap");
declare_lint!(pub LINKEDLIST, Warn,
              "usage of LinkedList, usually a vector is faster, or a more specialized data \
               structure like a RingBuf");

/// Matches a type with a provided string, and returns its type parameters if successful
pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> {
    match ty.node {
        TyPath(_, Path {segments: ref seg, ..}) => {
            // So ast::Path isn't the full path, just the tokens that were provided.
            // I could muck around with the maps and find the full path
            // however the more efficient way is to simply reverse the iterators and zip them
            // which will compare them in reverse until one of them runs out of segments
            if seg.iter().rev().zip(segments.iter().rev()).all(|(a,b)| a.identifier.name == b) {
                match seg[..].last() {
                    Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => {
                        Some(&a.types[..])
                    }
                    _ => None
                }
            } else {
                None
            }
        },
        _ => None
    }
}

#[allow(unused_imports)]
impl LintPass for TypePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOX_VEC, LINKEDLIST)
    }

    fn check_ty(&mut self, cx: &Context, ty: &ast::Ty) {
        {
            // In case stuff gets moved around
            use std::boxed::Box;
            use std::vec::Vec;
        }
        match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.first())
          .and_then(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"]))
          .map(|_| {
            span_help_and_lint(cx, BOX_VEC, ty.span,
                              "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?",
                              "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation");
          });
        {
            // In case stuff gets moved around
            use collections::linked_list::LinkedList as DL1;
            use std::collections::linked_list::LinkedList as DL2;
        }
        let dlists = [vec!["std","collections","linked_list","LinkedList"],
                      vec!["collections","linked_list","LinkedList"]];
        for path in &dlists {
            if match_ty_unwrap(ty, &path[..]).is_some() {
                span_help_and_lint(cx, LINKEDLIST, ty.span,
                                   "I see you're using a LinkedList! Perhaps you meant some other data structure?",
                                   "a RingBuf might work");
                return;
            }
        }
    }
}

#[allow(missing_copy_implementations)]
pub struct LetPass;

declare_lint!(pub LET_UNIT_VALUE, Warn,
              "creating a let binding to a value of unit type, which usually can't be used afterwards");

fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) {
    if in_macro(cx, info) { return; }
    if let DeclLocal(ref local) = decl.node {
        let bindtype = &cx.tcx.pat_ty(&*local.pat).sty;
        if *bindtype == ty::TyTuple(vec![]) {
            span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
                "this let-binding has unit value. Consider omitting `let {} =`",
                snippet(cx, local.pat.span, "..")));
        }
    }
}

impl LintPass for LetPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(LET_UNIT_VALUE)
    }

    fn check_decl(&mut self, cx: &Context, decl: &Decl) {
        cx.sess().codemap().with_expn_info(
            decl.span.expn_id,
            |info| check_let_unit(cx, decl, info));
    }
}

declare_lint!(pub UNIT_CMP, Warn,
              "comparing unit values (which is always `true` or `false`, respectively)");

#[allow(missing_copy_implementations)]
pub struct UnitCmp;

impl LintPass for UnitCmp {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_CMP)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, _) = expr.node {
            let op = cmp.node;
            let sty = &cx.tcx.expr_ty(left).sty;
            if *sty == ty::TyTuple(vec![]) && is_comparison_binop(op) {
                let result = match op {
                    BiEq | BiLe | BiGe => "true",
                    _ => "false"
                };
                span_lint(cx, UNIT_CMP, expr.span, &format!(
                    "{}-comparison of unit values detected. This will always be {}",
                    binop_to_string(op), result));
            }
        }
    }
}

pub struct CastPass;

declare_lint!(pub CAST_PRECISION_LOSS, Allow,
              "casts that cause loss of precision, e.g `x as f32` where `x: u64`");
declare_lint!(pub CAST_SIGN_LOSS, Allow,
              "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`");
declare_lint!(pub CAST_POSSIBLE_OVERFLOW, Allow,
              "casts that may cause overflow, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`");

impl LintPass for CastPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(CAST_PRECISION_LOSS,
                    CAST_SIGN_LOSS,
                    CAST_POSSIBLE_OVERFLOW)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprCast(ref ex, _) = expr.node {
            let (cast_from, cast_to) = (cx.tcx.expr_ty(&*ex), cx.tcx.expr_ty(expr));
            if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
                match (cast_from.is_integral(), cast_to.is_integral()) {
                    (true, false) => {
                        let from_nbits = match &cast_from.sty {
                            &ty::TyInt(i) =>  4 << (i as usize),
                            &ty::TyUint(u) => 4 << (u as usize),
                            _ => 0
                        };
                        let to_nbits : usize = match &cast_to.sty {
                            &ty::TyFloat(ast::TyF32) => 32,
                            &ty::TyFloat(ast::TyF64) => 64,
                            _ => 0
                        };
                        if from_nbits != 4 {
                            // Handle TyIs/TyUs separately (size is arch dependant)
                            if from_nbits >= to_nbits {
                                span_lint(cx, CAST_PRECISION_LOSS, expr.span,
                                          &format!("converting from {} to {}, which causes a loss of precision",
                                                   cast_from, cast_to));
                            }
                        }
                    },
                    (false, true) => {
                        span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span,
                                  &format!("the contents of a {} may overflow a {}", cast_from, cast_to));
                        if !cast_to.is_signed() {
                            span_lint(cx, CAST_SIGN_LOSS, expr.span,
                                      &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to));
                        }
                    },
                    (true, true) => {
                        if cast_from.is_signed() && !cast_to.is_signed() {
                            span_lint(cx, CAST_SIGN_LOSS, expr.span,
                                      &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to));
                        }
                        let from_nbits = match &cast_from.sty {
                            &ty::TyInt(i) =>  4 << (i as usize),
                            &ty::TyUint(u) => 4 << (u as usize),
                            _ => 0
                        };
                        let to_nbits = match &cast_to.sty {
                            &ty::TyInt(i) =>  4 << (i as usize),
                            &ty::TyUint(u) => 4 << (u as usize),
                            _ => 0
                        };
                        if to_nbits < from_nbits ||
                           (!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) {
                                span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span,
                                          &format!("the contents of a {} may overflow a {}", cast_from, cast_to));
                        }
                    }
                    (false, false) => {
                        if let (&ty::TyFloat(ast::TyF64),
                                &ty::TyFloat(ast::TyF32)) = (&cast_from.sty, &cast_to.sty) {
                            span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, "the contents of a f64 may overflow a f32");
                        }
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>
pub use num_complex::Complex32 as c32;
pub use num_complex::Complex64 as c64;
use num_traits::Float;
use std::ops::*;

pub trait AssociatedReal: Sized {
    type Real: Float + Mul<Self, Output = Self>;
}
pub trait AssociatedComplex: Sized {
    type Complex;
}

/// Field with norm
pub trait Absolute {
    type Output: Float;
    fn squared(&self) -> Self::Output;
    fn abs(&self) -> Self::Output {
        self.squared().sqrt()
    }
}

macro_rules! impl_traits {
    ($real:ty, $complex:ty) => {

impl AssociatedReal for $real {
    type Real = $real;
}

impl AssociatedReal for $complex {
    type Real = $real;
}

impl AssociatedComplex for $real {
    type Complex = $complex;
}

impl AssociatedComplex for $complex {
    type Complex = $complex;
}

impl Absolute for $real {
    type Output = Self;
    fn squared(&self) -> Self::Output {
        *self * *self
    }
    fn abs(&self) -> Self::Output {
        Float::abs(*self)
    }
}

impl Absolute for $complex {
    type Output = $real;
    fn squared(&self) -> Self::Output {
        self.norm_sqr()
    }
    fn abs(&self) -> Self::Output {
        self.norm()
    }
}

}} // impl_traits!

impl_traits!(f64, c64);
impl_traits!(f32, c32);
<commit_msg>Add Conjugate trait<commit_after>
pub use num_complex::Complex32 as c32;
pub use num_complex::Complex64 as c64;
use num_complex::Complex;
use num_traits::Float;
use std::ops::*;

pub trait AssociatedReal: Sized {
    type Real: Float + Mul<Self, Output = Self>;
}
pub trait AssociatedComplex: Sized {
    type Complex;
}

/// Field with norm
pub trait Absolute {
    type Output: Float;
    fn squared(&self) -> Self::Output;
    fn abs(&self) -> Self::Output {
        self.squared().sqrt()
    }
}

pub trait Conjugate: Copy {
    fn conj(self) -> Self;
}

macro_rules! impl_traits {
    ($real:ty, $complex:ty) => {

impl AssociatedReal for $real {
    type Real = $real;
}

impl AssociatedReal for $complex {
    type Real = $real;
}

impl AssociatedComplex for $real {
    type Complex = $complex;
}

impl AssociatedComplex for $complex {
    type Complex = $complex;
}

impl Absolute for $real {
    type Output = Self;
    fn squared(&self) -> Self::Output {
        *self * *self
    }
    fn abs(&self) -> Self::Output {
        Float::abs(*self)
    }
}

impl Absolute for $complex {
    type Output = $real;
    fn squared(&self) -> Self::Output {
        self.norm_sqr()
    }
    fn abs(&self) -> Self::Output {
        self.norm()
    }
}

impl Conjugate for $real {
    fn conj(self) -> Self {
        self
    }
}

impl Conjugate for $complex {
    fn conj(self) -> Self {
        Complex::conj(&self)
    }
}

}} // impl_traits!

impl_traits!(f64, c64);
impl_traits!(f32, c32);
<|endoftext|>


<commit_before>/// "Signaling" trait used in impl trait to tag lifetimes that you may
/// need to capture but don't really need for other reasons.
/// Basically a workaround; see [this comment] for details.
///
/// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
// FIXME(eddyb) false positive, the lifetime parameter is "phantom" but needed.
#[allow(unused_lifetimes)]
pub trait Captures<'a> {}

impl<'a, T: ?Sized> Captures<'a> for T {}
<commit_msg>Rollup merge of #86387 - JohnTitor:now-no-unused-lifetimes, r=Mark-Simulacrum<commit_after>/// "Signaling" trait used in impl trait to tag lifetimes that you may
/// need to capture but don't really need for other reasons.
/// Basically a workaround; see [this comment] for details.
///
/// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
pub trait Captures<'a> {}

impl<'a, T: ?Sized> Captures<'a> for T {}
<|endoftext|>


<commit_before>// Used internally for evalulating expressions
// Note: for now, negative is falsy and positive (including zero) is truthy

use interpreter::lexer::Token;
use interpreter::lexer;
use std::collections::HashMap;
use std::collections::hashmap::{Occupied, Vacant};
use std::num;

#[deriving(Show)]
enum ExprToken<'a> {
	Op(Operator),
	Value(f32),
	Var(uint),
	LParen,
	RParen,
}

#[deriving(Show)]
enum Operator {
	Add,
	Sub,
	Mul,
	Div,
	Exp,
	Mod,
	Neg,
	Less,
	Greater,
	Equ,
	NotEqu,
	ApproxEqu,
	Not,
	And,
	Or,
	Xor,
	GreaterEqual,
	LessEqual,
}

fn precedence(op: Operator) -> int {
	match op {
		Equ | NotEqu | ApproxEqu => 1,
		Less | Greater | GreaterEqual | LessEqual => 2,
		And | Or | Xor => 0,
		Add => 3,
		Sub => 3,
		Mul => 4,
		Div => 4,
		Mod => 4,
		Neg => 6,
		Not => 6,
		Exp => 6,
	}
}

fn nargs(op: Operator) -> uint {
	match op {
		Neg | Not => 1,
		_ => 2,
	}
}

#[deriving(PartialEq)]
enum Associativity {
	Left,
	Right,
}

fn associativity(op: Operator) -> Associativity {
	match op {
		Exp => Right,
		_ => Left,
	}
}

#[deriving(Show)]
pub struct Expression<'a> {
	rpn: Vec<ExprToken<'a>>, // reverse polish notation
	var_values: Vec<f32>, // values of vars by id
	vars: HashMap<&'a str, uint>, // map of var name -> var id
	value: Option<f32>, // holds the last value of the expression, if it's been evaluated and vars have not been updated
}

impl<'a> Expression<'a> {
	// converts a token slice from the lexer into an expression that can be evaluated
	pub fn new<'a>(tok: Vec<Token<'a>>) -> Expression {
		let mut vars: HashMap<&'a str, uint> = HashMap::new();
		let out: Vec<ExprToken<'a>> = tok.iter().filter_map(|&t| {
			match t {
				// Try to parse constants as f32. subject to maybe change but probably not.
				lexer::Const(v) => {
					if let Some(x) = from_str::<f32>(v) {
						Some(Value(x))
					} else {
						fail!("invalid const, regex must be broken!");
					}
				},
				lexer::Operator(v) => {
					Some(Op(match v {
						"+" => Add,
						"-" => Sub,
						"*" => Mul,
						"/" => Div,
						"^" => Exp,
						"%" => Mod,
						"==" => Equ,
						"!=" => NotEqu,
						"~=" => ApproxEqu,
						"<" => Less,
						">" => Greater,
						"<=" => LessEqual,
						">=" => GreaterEqual,
						"!" => Not,
						"&&" => And,
						"||" => Or,
						"^^" => Xor,
						_ => fail!("unexpected operator"),
					}))
				},
				lexer::Paren(v) => {
					if v == "(" {
						Some(LParen)
					} else if v == ")" {
						Some(RParen)
					} else {
						None
					}
				},
				// An identifier in the context of an expression is always a variable (TODO FALSE!!)
				lexer::Ident(v) => {
					let nv = vars.len();
					match vars.entry(v) {
						Occupied(entry) => {
							Some(Var(*entry.get()))
						},
						Vacant(entry) => {
							entry.set(nv);
							Some(Var(nv))
						},
					}
				},
				// Discard whitesapce
				lexer::Whitespace(_) | lexer::Newline => {
					None
				},
				_ => {
					fail!("not expression!");
				}
			}
		}).collect();

		// Handle special case with unary minus
		// If an subtraction operator is preceded by another operator, left paren, or the start of the
		// expression, make it a negation operator.
		let out = out.iter().enumerate().map(|(i, &v)| {
			match v {
				Op(Sub) => {
					if i == 0 || match out[i-1] { Op(_) | LParen => true, _ => false } {
						Op(Neg)
					} else {
						v
					}
				},
				_ => v,
			}
		}).collect();

		Expression {
			rpn: shunting_yard(out),
			var_values: Vec::from_elem(vars.len(), 0f32),
			vars: vars,
			value: None,
		}
	}

	// http://en.wikipedia.org/wiki/Reverse_Polish_notation
	pub fn eval(&mut self) -> f32 {
		// If the expression is constant, return it's value
		if let Some(v) = self.value {
			return v;
		}

		let mut stack: Vec<f32> = Vec::new();
		for &t in self.rpn.iter() {
			match t {
				Value(v) => {
					stack.push(v);
				},
				Op(op) => {
					let n = nargs(op);
					if stack.len() < n {
						fail!("invalid expression: not enough args for operator {}", op);
					}
					let args: Vec<f32> = range(0, n).map(|_| stack.pop().unwrap()).collect();
					stack.push(match op {
						Add => {
							args[1] + args[0]
						},
						Sub => {
							args[1] - args[0]
						},
						Mul => {
							args[1] * args[0]
						},
						Div => {
							args[1] / args[0]
						},
						Exp => {
							args[1].powf(args[0])
						},
						Mod => {
							let c = num::abs(args[1]/args[0]).fract()*num::abs(args[0]);
							if args[1] < 0f32 { -c } else { c }
						},
						Neg => {
							-args[0]
						},
						Not => {
							if args[0] > 0f32 { -1f32 } else { 1f32 }
						},
						Less => {
							if args[1] < args[0] { 1f32 } else { -1f32 }
						},
						Greater => {
							if args[1] > args[0] { 1f32 } else { -1f32 }
						},
						LessEqual => {
							if args[1] <= args[0] { 1f32 } else { -1f32 }
						},
						GreaterEqual => {
							if args[1] >= args[0] { 1f32 } else { -1f32 }
						},
						Equ => {
							if args[1] == args[0] { 1f32 } else { -1f32 }
						},
						NotEqu => {
							if args[1] != args[0] { 1f32 } else { -1f32 }
						},
						ApproxEqu => {
							if num::abs(args[1] - args[0]) < 0.0001 { 1f32 } else { -1f32 }
						},
						And => {
							if args[1] > 0f32 && args[0] > 0f32 { 1f32 } else { -1f32 }
						},
						Or => {
							if args[1] > 0f32 || args[0] > 0f32 { 1f32 } else { -1f32 }
						},
						Xor => {
							if (args[1] > 0f32) ^ (args[0] > 0f32) { 1f32 } else { -1f32 }
						},
					});
				},
				Var(id) => {
					stack.push(self.var_values[id]);
				},
				_ => fail!("unexpected token in expression"),
			};
		}
		match stack.len() {
			1 => {
				let val = stack.pop().unwrap();
				self.value = Some(val);
				val
			},
			0 => {
				fail!("zero values in expression");
			},
			_ => {
				fail!("to many values in expression");
			},
		}
	}

	pub fn var_id(&self, var: &'a str) -> Option<uint> {
		match self.vars.find(&var) {
			Some(v) => Some(*v),
			None => None,
		}
	}

	pub fn set_var(&mut self, var_id: uint, value: f32) {
		if var_id > self.var_values.len() {
			fail!("invalid var id passed to set_var");
		}
		self.var_values[var_id] = value;
		self.value = None // Setting a var clears evaled value
	}

	pub fn try_set_var(&mut self, var: &'a str, value: f32) {
		if let Some(id) = self.var_id(var) {
			self.set_var(id, value);
		}
	}
}

// http://en.wikipedia.org/wiki/Shunting-yard_algorithm
fn shunting_yard(tok: Vec<ExprToken>) -> Vec<ExprToken> {
	let mut out = Vec::new();
	let mut stack: Vec<ExprToken> = Vec::new();
	for &t in tok.iter() {
		match t {
			Value(_) | Var(_) => {
				out.push(t);
			}
			Op(op1) => {
				while stack.len() > 0 {
					let top = stack[stack.len()-1];
					match top {
						Op(op2) => {
							if (associativity(op1) == Left && precedence(op1) <= precedence(op2)) ||
								(precedence(op1) < precedence(op2)) {
								stack.pop();
								out.push(top);
							} else {
								break;
							}
						},
						_ => break,
					}
				}
				stack.push(t);
			},
			LParen => {
				stack.push(t);
			},
			RParen => {
				let mut foundleft = false;
				while stack.len() > 0 {
					let op = stack.pop().unwrap();
					match op {
						Op(_) => {
							out.push(op);
						},
						LParen => {
							foundleft = true;
							break;
						},
						_ => fail!("not sure how this can happen, but maybe"),
					}
				}
				if !foundleft {
					fail!("mismatched parens");
				}
			},
		};
	}
	while stack.len() > 0 {
		let top = stack[stack.len()-1];
		match top {
			Op(_) => {
				stack.pop();
				out.push(top);
			},
			LParen | RParen => fail!("mismatched parens"),
			_ => fail!("non operator on stack!"),
		}
	}
	out
}
<commit_msg>Some docs & fixes with setting variables in expressions.<commit_after>// Used internally for evalulating expressions
// Note: for now, negative is falsy and positive (including zero) is truthy

use interpreter::lexer::Token;
use interpreter::lexer;
use std::collections::HashMap;
use std::collections::hashmap::{Occupied, Vacant};
use std::num;

#[deriving(Show)]
enum ExprToken<'a> {
	Op(Operator),
	Value(f32),
	Var(uint),
	LParen,
	RParen,
}

#[deriving(Show)]
enum Operator {
	Add,
	Sub,
	Mul,
	Div,
	Exp,
	Mod,
	Neg,
	Less,
	Greater,
	Equ,
	NotEqu,
	ApproxEqu,
	Not,
	And,
	Or,
	Xor,
	GreaterEqual,
	LessEqual,
}

fn precedence(op: Operator) -> int {
	match op {
		Equ | NotEqu | ApproxEqu => 1,
		Less | Greater | GreaterEqual | LessEqual => 2,
		And | Or | Xor => 0,
		Add => 3,
		Sub => 3,
		Mul => 4,
		Div => 4,
		Mod => 4,
		Neg => 6,
		Not => 6,
		Exp => 6,
	}
}

fn nargs(op: Operator) -> uint {
	match op {
		Neg | Not => 1,
		_ => 2,
	}
}

#[deriving(PartialEq)]
enum Associativity {
	Left,
	Right,
}

fn associativity(op: Operator) -> Associativity {
	match op {
		Exp => Right,
		_ => Left,
	}
}

#[deriving(Show)]
pub struct Expression<'a> {
	rpn: Vec<ExprToken<'a>>, // reverse polish notation
	var_values: Vec<f32>, // values of vars by id
	vars: HashMap<&'a str, uint>, // map of var name -> var id
	value: Option<f32>, // holds the last value of the expression, if it's been evaluated and vars have not been updated
}

impl<'a> Expression<'a> {
	// converts a token slice from the lexer into an expression that can be evaluated
	pub fn new<'a>(tok: Vec<Token<'a>>) -> Expression {
		let mut vars: HashMap<&'a str, uint> = HashMap::new();
		let out: Vec<ExprToken<'a>> = tok.iter().filter_map(|&t| {
			match t {
				// Try to parse constants as f32. subject to maybe change but probably not.
				lexer::Const(v) => {
					if let Some(x) = from_str::<f32>(v) {
						Some(Value(x))
					} else {
						fail!("invalid const, regex must be broken!");
					}
				},
				lexer::Operator(v) => {
					Some(Op(match v {
						"+" => Add,
						"-" => Sub,
						"*" => Mul,
						"/" => Div,
						"^" => Exp,
						"%" => Mod,
						"==" => Equ,
						"!=" => NotEqu,
						"~=" => ApproxEqu,
						"<" => Less,
						">" => Greater,
						"<=" => LessEqual,
						">=" => GreaterEqual,
						"!" => Not,
						"&&" => And,
						"||" => Or,
						"^^" => Xor,
						_ => fail!("unexpected operator"),
					}))
				},
				lexer::Paren(v) => {
					if v == "(" {
						Some(LParen)
					} else if v == ")" {
						Some(RParen)
					} else {
						None
					}
				},
				// An identifier in the context of an expression is always a variable (TODO FALSE!!)
				lexer::Ident(v) => {
					let nv = vars.len();
					match vars.entry(v) {
						Occupied(entry) => {
							Some(Var(*entry.get()))
						},
						Vacant(entry) => {
							entry.set(nv);
							Some(Var(nv))
						},
					}
				},
				// Discard whitesapce
				lexer::Whitespace(_) | lexer::Newline => {
					None
				},
				_ => {
					fail!("not expression!");
				}
			}
		}).collect();

		// Handle special case with unary minus
		// If an subtraction operator is preceded by another operator, left paren, or the start of the
		// expression, make it a negation operator.
		let out = out.iter().enumerate().map(|(i, &v)| {
			match v {
				Op(Sub) => {
					if i == 0 || match out[i-1] { Op(_) | LParen => true, _ => false } {
						Op(Neg)
					} else {
						v
					}
				},
				_ => v,
			}
		}).collect();

		Expression {
			rpn: shunting_yard(out),
			var_values: Vec::from_elem(vars.len(), 0f32),
			vars: vars,
			value: None,
		}
	}

	// http://en.wikipedia.org/wiki/Reverse_Polish_notation
	pub fn eval(&mut self) -> f32 {
		// If the expression is constant, return it's value
		if let Some(v) = self.value {
			return v;
		}

		let mut stack: Vec<f32> = Vec::new();
		for &t in self.rpn.iter() {
			match t {
				Value(v) => {
					stack.push(v);
				},
				Op(op) => {
					let n = nargs(op);
					if stack.len() < n {
						fail!("invalid expression: not enough args for operator {}", op);
					}
					let args: Vec<f32> = range(0, n).map(|_| stack.pop().unwrap()).collect();
					stack.push(match op {
						Add => {
							args[1] + args[0]
						},
						Sub => {
							args[1] - args[0]
						},
						Mul => {
							args[1] * args[0]
						},
						Div => {
							args[1] / args[0]
						},
						Exp => {
							args[1].powf(args[0])
						},
						Mod => {
							let c = num::abs(args[1]/args[0]).fract()*num::abs(args[0]);
							if args[1] < 0f32 { -c } else { c }
						},
						Neg => {
							-args[0]
						},
						Not => {
							if args[0] > 0f32 { -1f32 } else { 1f32 }
						},
						Less => {
							if args[1] < args[0] { 1f32 } else { -1f32 }
						},
						Greater => {
							if args[1] > args[0] { 1f32 } else { -1f32 }
						},
						LessEqual => {
							if args[1] <= args[0] { 1f32 } else { -1f32 }
						},
						GreaterEqual => {
							if args[1] >= args[0] { 1f32 } else { -1f32 }
						},
						Equ => {
							if args[1] == args[0] { 1f32 } else { -1f32 }
						},
						NotEqu => {
							if args[1] != args[0] { 1f32 } else { -1f32 }
						},
						ApproxEqu => {
							if num::abs(args[1] - args[0]) < 0.0001 { 1f32 } else { -1f32 }
						},
						And => {
							if args[1] > 0f32 && args[0] > 0f32 { 1f32 } else { -1f32 }
						},
						Or => {
							if args[1] > 0f32 || args[0] > 0f32 { 1f32 } else { -1f32 }
						},
						Xor => {
							if (args[1] > 0f32) ^ (args[0] > 0f32) { 1f32 } else { -1f32 }
						},
					});
				},
				Var(id) => {
					stack.push(self.var_values[id]);
				},
				_ => fail!("unexpected token in expression"),
			};
		}
		match stack.len() {
			1 => {
				let val = stack.pop().unwrap();
				self.value = Some(val);
				val
			},
			0 => {
				fail!("zero values in expression");
			},
			_ => {
				fail!("to many values in expression");
			},
		}
	}

	// Returns a uint identifier which can be passed to set_var to quickly update the value of a
	// variable.
	pub fn var_id(&self, var: &'a str) -> Option<uint> {
		match self.vars.find(&var) {
			Some(v) => Some(*v),
			None => None,
		}
	}

	// Sets a variable to an id retrieved from var_id. Return value indicates whether it was set
	// sucessfully or not.
	pub fn set_var(&mut self, var_id: uint, value: f32) -> bool {
		if var_id > self.var_values.len() {
			return false;
		}
		self.var_values[var_id] = value;
		self.value = None; // Setting a var clears evaled value
		true
	}

	// Attempts to set a variable by name. If the variable does not exist, nothing is done.
	pub fn try_set_var(&mut self, var: &'a str, value: f32) {
		if let Some(id) = self.var_id(var) {
			self.set_var(id, value);
		}
	}
}

// http://en.wikipedia.org/wiki/Shunting-yard_algorithm
fn shunting_yard(tok: Vec<ExprToken>) -> Vec<ExprToken> {
	let mut out = Vec::new();
	let mut stack: Vec<ExprToken> = Vec::new();
	for &t in tok.iter() {
		match t {
			Value(_) | Var(_) => {
				out.push(t);
			}
			Op(op1) => {
				while stack.len() > 0 {
					let top = stack[stack.len()-1];
					match top {
						Op(op2) => {
							if (associativity(op1) == Left && precedence(op1) <= precedence(op2)) ||
								(precedence(op1) < precedence(op2)) {
								stack.pop();
								out.push(top);
							} else {
								break;
							}
						},
						_ => break,
					}
				}
				stack.push(t);
			},
			LParen => {
				stack.push(t);
			},
			RParen => {
				let mut foundleft = false;
				while stack.len() > 0 {
					let op = stack.pop().unwrap();
					match op {
						Op(_) => {
							out.push(op);
						},
						LParen => {
							foundleft = true;
							break;
						},
						_ => fail!("not sure how this can happen, but maybe"),
					}
				}
				if !foundleft {
					fail!("mismatched parens");
				}
			},
		};
	}
	while stack.len() > 0 {
		let top = stack[stack.len()-1];
		match top {
			Op(_) => {
				stack.pop();
				out.push(top);
			},
			LParen | RParen => fail!("mismatched parens"),
			_ => fail!("non operator on stack!"),
		}
	}
	out
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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::collections::HashMap;
use std::io;
use std::mem;

use core::os::process::handle_from_pid;
use core::os::process::windows_child::{Child, ExitStatus, Handle};
use kernel32;
use protocol::{self, ShutdownMethod};
use time::{Duration, SteadyTime};
use winapi;

use error::{Error, Result};
use service::Service;

const PROCESS_ACTIVE: u32 = 259;
type ProcessTable = HashMap<winapi::DWORD, Vec<winapi::DWORD>>;

pub struct Process {
    handle: Handle,
    last_status: Option<ExitStatus>,
}

impl Process {
    fn new(handle: Handle) -> Self {
        Process {
            handle: handle,
            last_status: None,
        }
    }

    pub fn id(&self) -> u32 {
        unsafe { kernel32::GetProcessId(self.handle.raw()) as u32 }
    }

    pub fn kill(&mut self) -> ShutdownMethod {
        if self.status().is_some() {
            return ShutdownMethod::AlreadyExited;
        }
        let ret = unsafe { kernel32::GenerateConsoleCtrlEvent(1, self.id()) };
        if ret == 0 {
            debug!(
                "Failed to send ctrl-break to pid {}: {}",
                self.id(),
                io::Error::last_os_error()
            );
        }

        let stop_time = SteadyTime::now() + Duration::seconds(8);
        loop {
            if ret == 0 || SteadyTime::now() > stop_time {
                let proc_table = build_proc_table();
                terminate_process_descendants(&proc_table, self.id());
                return ShutdownMethod::Killed;
            }

            if self.status().is_some() {
                return ShutdownMethod::GracefulTermination;
            }
        }
    }

    pub fn wait(&mut self) -> Result<ExitStatus> {
        unsafe {
            let res = kernel32::WaitForSingleObject(self.handle.raw(), winapi::INFINITE);
            if res != winapi::WAIT_OBJECT_0 {
                return Err(Error::ExecWait(io::Error::last_os_error()));
            }
            let mut status = 0;
            cvt(kernel32::GetExitCodeProcess(self.handle.raw(), &mut status))
                .map_err(Error::ExecWait)?;
            Ok(ExitStatus::from(status))
        }
    }

    pub fn try_wait(&mut self) -> Result<Option<ExitStatus>> {
        unsafe {
            match kernel32::WaitForSingleObject(self.handle.raw(), 0) {
                winapi::WAIT_OBJECT_0 => {}
                winapi::WAIT_TIMEOUT => return Ok(None),
                _ => return Err(Error::ExecWait(io::Error::last_os_error())),
            }
            let mut status = 0;
            cvt(kernel32::GetExitCodeProcess(self.handle.raw(), &mut status))
                .map_err(Error::ExecWait)?;
            Ok(Some(ExitStatus::from(status)))
        }
    }

    fn status(&mut self) -> Option<ExitStatus> {
        if self.last_status.is_some() {
            return self.last_status;
        }
        match exit_code(&self.handle) {
            Some(PROCESS_ACTIVE) => None,
            Some(code) => {
                self.last_status = Some(ExitStatus::from(code));
                self.last_status
            }
            None => None,
        }
    }
}

pub fn run(mut msg: protocol::Spawn) -> Result<Service> {
    debug!("launcher is spawning {}", msg.get_binary());
    let ps_cmd = format!("iex $(gc {} | out-string)", msg.get_binary());
    let password = if msg.get_svc_password().is_empty() {
        None
    } else {
        Some(msg.take_svc_password())
    };
    match Child::spawn(
        "pwsh.exe",
        vec!["-NonInteractive", "-command", ps_cmd.as_str()],
        msg.get_env(),
        msg.get_svc_user(),
        password,
    ) {
        Ok(child) => {
            let process = Process::new(child.handle);
            Ok(Service::new(msg, process, child.stdout, child.stderr))
        }
        Err(_) => Err(Error::Spawn(io::Error::last_os_error())),
    }
}

fn build_proc_table() -> ProcessTable {
    let processes_snap_handle =
        unsafe { kernel32::CreateToolhelp32Snapshot(winapi::TH32CS_SNAPPROCESS, 0) };

    if processes_snap_handle == winapi::INVALID_HANDLE_VALUE {
        error!(
            "Failed to call CreateToolhelp32Snapshot: {}",
            io::Error::last_os_error()
        );
        return ProcessTable::new();
    }
    let mut table = ProcessTable::new();
    let mut process_entry = winapi::PROCESSENTRY32W {
        dwSize: mem::size_of::<winapi::PROCESSENTRY32W>() as u32,
        cntUsage: 0,
        th32ProcessID: 0,
        th32DefaultHeapID: 0,
        th32ModuleID: 0,
        cntThreads: 0,
        th32ParentProcessID: 0,
        pcPriClassBase: 0,
        dwFlags: 0,
        szExeFile: [0; winapi::MAX_PATH],
    };
    // Get the first process from the snapshot.
    match unsafe { kernel32::Process32FirstW(processes_snap_handle, &mut process_entry) } {
        1 => {
            // First process worked, loop to find the process with the correct name.
            let mut process_success: i32 = 1;
            // Loop through all processes until we find one where `szExeFile` == `name`.
            while process_success == 1 {
                let children = table.entry(process_entry.th32ParentProcessID).or_insert(
                    Vec::new(),
                );
                (*children).push(process_entry.th32ProcessID);
                process_success =
                    unsafe { kernel32::Process32NextW(processes_snap_handle, &mut process_entry) };
            }
            unsafe { kernel32::CloseHandle(processes_snap_handle) };
        }
        0 | _ => unsafe {
            kernel32::CloseHandle(processes_snap_handle);
        },
    }
    table
}

fn cvt(i: i32) -> io::Result<i32> {
    if i == 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(i)
    }
}

fn exit_code(handle: &Handle) -> Option<u32> {
    let mut exit_code: u32 = 0;
    unsafe {
        let ret = kernel32::GetExitCodeProcess(handle.raw(), &mut exit_code as winapi::LPDWORD);
        if ret == 0 {
            error!(
                "Failed to retrieve Exit Code: {}",
                io::Error::last_os_error()
            );
            return None;
        }
    }
    Some(exit_code)
}

fn terminate_process_descendants(table: &ProcessTable, pid: winapi::DWORD) {
    if let Some(children) = table.get(&pid) {
        for child in children {
            terminate_process_descendants(table, child.clone());
        }
    }
    unsafe {
        match handle_from_pid(pid) {
            Some(h) => {
                if kernel32::TerminateProcess(h, 1) == 0 {
                    error!(
                        "Failed to call TerminateProcess on pid {}: {}",
                        pid,
                        io::Error::last_os_error()
                    );
                }
            }
            None => {}
        }
    }
}
<commit_msg>fallback to older powershell binary name if newer one is not installed<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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::collections::HashMap;
use std::io;
use std::mem;

use core::os::process::handle_from_pid;
use core::os::process::windows_child::{Child, ExitStatus, Handle};
use kernel32;
use protocol::{self, ShutdownMethod};
use time::{Duration, SteadyTime};
use winapi;

use error::{Error, Result};
use service::Service;

const PROCESS_ACTIVE: u32 = 259;
type ProcessTable = HashMap<winapi::DWORD, Vec<winapi::DWORD>>;

pub struct Process {
    handle: Handle,
    last_status: Option<ExitStatus>,
}

impl Process {
    fn new(handle: Handle) -> Self {
        Process {
            handle: handle,
            last_status: None,
        }
    }

    pub fn id(&self) -> u32 {
        unsafe { kernel32::GetProcessId(self.handle.raw()) as u32 }
    }

    pub fn kill(&mut self) -> ShutdownMethod {
        if self.status().is_some() {
            return ShutdownMethod::AlreadyExited;
        }
        let ret = unsafe { kernel32::GenerateConsoleCtrlEvent(1, self.id()) };
        if ret == 0 {
            debug!(
                "Failed to send ctrl-break to pid {}: {}",
                self.id(),
                io::Error::last_os_error()
            );
        }

        let stop_time = SteadyTime::now() + Duration::seconds(8);
        loop {
            if ret == 0 || SteadyTime::now() > stop_time {
                let proc_table = build_proc_table();
                terminate_process_descendants(&proc_table, self.id());
                return ShutdownMethod::Killed;
            }

            if self.status().is_some() {
                return ShutdownMethod::GracefulTermination;
            }
        }
    }

    pub fn wait(&mut self) -> Result<ExitStatus> {
        unsafe {
            let res = kernel32::WaitForSingleObject(self.handle.raw(), winapi::INFINITE);
            if res != winapi::WAIT_OBJECT_0 {
                return Err(Error::ExecWait(io::Error::last_os_error()));
            }
            let mut status = 0;
            cvt(kernel32::GetExitCodeProcess(self.handle.raw(), &mut status))
                .map_err(Error::ExecWait)?;
            Ok(ExitStatus::from(status))
        }
    }

    pub fn try_wait(&mut self) -> Result<Option<ExitStatus>> {
        unsafe {
            match kernel32::WaitForSingleObject(self.handle.raw(), 0) {
                winapi::WAIT_OBJECT_0 => {}
                winapi::WAIT_TIMEOUT => return Ok(None),
                _ => return Err(Error::ExecWait(io::Error::last_os_error())),
            }
            let mut status = 0;
            cvt(kernel32::GetExitCodeProcess(self.handle.raw(), &mut status))
                .map_err(Error::ExecWait)?;
            Ok(Some(ExitStatus::from(status)))
        }
    }

    fn status(&mut self) -> Option<ExitStatus> {
        if self.last_status.is_some() {
            return self.last_status;
        }
        match exit_code(&self.handle) {
            Some(PROCESS_ACTIVE) => None,
            Some(code) => {
                self.last_status = Some(ExitStatus::from(code));
                self.last_status
            }
            None => None,
        }
    }
}

pub fn run(msg: protocol::Spawn) -> Result<Service> {
    // Supervisors prior to version 0.53.0 pulled in beta versions of
    // powershell. The official 6.0.0 version of powershell changed
    // the name of the powershell binary to pwsh.exe. Here we will
    // first attempt the latest binary name and fall back to the
    // former name.
    match spawn_pwsh("pwsh.exe", msg.clone()) {
        Ok(service) => Ok(service),
        Err(err) => {
            if err.raw_os_error() == Some(winapi::ERROR_FILE_NOT_FOUND as i32) {
                spawn_pwsh("powershell.exe", msg).map_err(Error::Spawn)
            } else {
                Err(Error::Spawn(err))
            }
        }
    }
}

fn spawn_pwsh(ps_binary_name: &str, mut msg: protocol::Spawn) -> io::Result<Service> {
    debug!("launcher is spawning {}", msg.get_binary());
    let ps_cmd = format!("iex $(gc {} | out-string)", msg.get_binary());
    let password = if msg.get_svc_password().is_empty() {
        None
    } else {
        Some(msg.take_svc_password())
    };
    match Child::spawn(
        ps_binary_name,
        vec!["-NonInteractive", "-command", ps_cmd.as_str()],
        msg.get_env(),
        msg.get_svc_user(),
        password,
    ) {
        Ok(child) => {
            let process = Process::new(child.handle);
            Ok(Service::new(msg, process, child.stdout, child.stderr))
        }
        Err(_) => Err(io::Error::last_os_error()),
    }
}

fn build_proc_table() -> ProcessTable {
    let processes_snap_handle =
        unsafe { kernel32::CreateToolhelp32Snapshot(winapi::TH32CS_SNAPPROCESS, 0) };

    if processes_snap_handle == winapi::INVALID_HANDLE_VALUE {
        error!(
            "Failed to call CreateToolhelp32Snapshot: {}",
            io::Error::last_os_error()
        );
        return ProcessTable::new();
    }
    let mut table = ProcessTable::new();
    let mut process_entry = winapi::PROCESSENTRY32W {
        dwSize: mem::size_of::<winapi::PROCESSENTRY32W>() as u32,
        cntUsage: 0,
        th32ProcessID: 0,
        th32DefaultHeapID: 0,
        th32ModuleID: 0,
        cntThreads: 0,
        th32ParentProcessID: 0,
        pcPriClassBase: 0,
        dwFlags: 0,
        szExeFile: [0; winapi::MAX_PATH],
    };
    // Get the first process from the snapshot.
    match unsafe { kernel32::Process32FirstW(processes_snap_handle, &mut process_entry) } {
        1 => {
            // First process worked, loop to find the process with the correct name.
            let mut process_success: i32 = 1;
            // Loop through all processes until we find one where `szExeFile` == `name`.
            while process_success == 1 {
                let children = table.entry(process_entry.th32ParentProcessID).or_insert(
                    Vec::new(),
                );
                (*children).push(process_entry.th32ProcessID);
                process_success =
                    unsafe { kernel32::Process32NextW(processes_snap_handle, &mut process_entry) };
            }
            unsafe { kernel32::CloseHandle(processes_snap_handle) };
        }
        0 | _ => unsafe {
            kernel32::CloseHandle(processes_snap_handle);
        },
    }
    table
}

fn cvt(i: i32) -> io::Result<i32> {
    if i == 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(i)
    }
}

fn exit_code(handle: &Handle) -> Option<u32> {
    let mut exit_code: u32 = 0;
    unsafe {
        let ret = kernel32::GetExitCodeProcess(handle.raw(), &mut exit_code as winapi::LPDWORD);
        if ret == 0 {
            error!(
                "Failed to retrieve Exit Code: {}",
                io::Error::last_os_error()
            );
            return None;
        }
    }
    Some(exit_code)
}

fn terminate_process_descendants(table: &ProcessTable, pid: winapi::DWORD) {
    if let Some(children) = table.get(&pid) {
        for child in children {
            terminate_process_descendants(table, child.clone());
        }
    }
    unsafe {
        match handle_from_pid(pid) {
            Some(h) => {
                if kernel32::TerminateProcess(h, 1) == 0 {
                    error!(
                        "Failed to call TerminateProcess on pid {}: {}",
                        pid,
                        io::Error::last_os_error()
                    );
                }
            }
            None => {}
        }
    }
}
<|endoftext|>


<commit_before>use core::fmt::{self, Debug};
use core::ops::{Deref, DerefMut};

#[cfg(feature = "alloc")]
use alloc::borrow::ToOwned;

#[cfg(any(feature = "std", feature = "alloc"))]
use crate::ByteBuf;

use serde::de::{Deserialize, Deserializer, Error, Visitor};
use serde::ser::{Serialize, Serializer};

/// Wrapper around `&[u8]` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::Bytes;
///
/// fn print_encoded_cache() -> bincode::Result<()> {
///     let mut cache = HashMap::new();
///     cache.insert(3, Bytes::new(b"three"));
///     cache.insert(2, Bytes::new(b"two"));
///     cache.insert(1, Bytes::new(b"one"));
///
///     bincode::serialize_into(&mut io::stdout(), &cache)
/// }
/// #
/// # fn main() {
/// #     print_encoded_cache().unwrap();
/// # }
/// ```
#[derive(Eq, Hash, PartialEq, PartialOrd, Ord)]
#[repr(C)]
pub struct Bytes {
    bytes: [u8],
}

impl Bytes {
    /// Wrap an existing `&[u8]`.
    pub fn new(bytes: &[u8]) -> &Self {
        unsafe { &*(bytes as *const [u8] as *const Bytes) }
    }
}

impl Debug for Bytes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.bytes, f)
    }
}

impl Deref for Bytes {
    type Target = [u8];

    fn deref(&self) -> &Self::Target {
        &self.bytes
    }
}

impl DerefMut for Bytes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.bytes
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl ToOwned for Bytes {
    type Owned = ByteBuf;

    fn to_owned(&self) -> Self::Owned {
        ByteBuf::from(&self.bytes)
    }
}

impl Serialize for Bytes {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&self.bytes)
    }
}

struct BytesVisitor;

impl<'de> Visitor<'de> for BytesVisitor {
    type Value = &'de Bytes;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a borrowed byte array")
    }

    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v))
    }

    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v.as_bytes()))
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for &'a Bytes {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(BytesVisitor)
    }
}
<commit_msg>Provide AsRef<[u8]> for Bytes<commit_after>use core::fmt::{self, Debug};
use core::ops::{Deref, DerefMut};

#[cfg(feature = "alloc")]
use alloc::borrow::ToOwned;

#[cfg(any(feature = "std", feature = "alloc"))]
use crate::ByteBuf;

use serde::de::{Deserialize, Deserializer, Error, Visitor};
use serde::ser::{Serialize, Serializer};

/// Wrapper around `&[u8]` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::Bytes;
///
/// fn print_encoded_cache() -> bincode::Result<()> {
///     let mut cache = HashMap::new();
///     cache.insert(3, Bytes::new(b"three"));
///     cache.insert(2, Bytes::new(b"two"));
///     cache.insert(1, Bytes::new(b"one"));
///
///     bincode::serialize_into(&mut io::stdout(), &cache)
/// }
/// #
/// # fn main() {
/// #     print_encoded_cache().unwrap();
/// # }
/// ```
#[derive(Eq, Hash, PartialEq, PartialOrd, Ord)]
#[repr(C)]
pub struct Bytes {
    bytes: [u8],
}

impl Bytes {
    /// Wrap an existing `&[u8]`.
    pub fn new(bytes: &[u8]) -> &Self {
        unsafe { &*(bytes as *const [u8] as *const Bytes) }
    }
}

impl Debug for Bytes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.bytes, f)
    }
}

impl AsRef<[u8]> for Bytes {
    fn as_ref(&self) -> &[u8] {
        &self.bytes
    }
}

impl AsMut<[u8]> for Bytes {
    fn as_mut(&mut self) -> &mut [u8] {
        &mut self.bytes
    }
}

impl Deref for Bytes {
    type Target = [u8];

    fn deref(&self) -> &Self::Target {
        &self.bytes
    }
}

impl DerefMut for Bytes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.bytes
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl ToOwned for Bytes {
    type Owned = ByteBuf;

    fn to_owned(&self) -> Self::Owned {
        ByteBuf::from(&self.bytes)
    }
}

impl Serialize for Bytes {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&self.bytes)
    }
}

struct BytesVisitor;

impl<'de> Visitor<'de> for BytesVisitor {
    type Value = &'de Bytes;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a borrowed byte array")
    }

    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v))
    }

    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v.as_bytes()))
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for &'a Bytes {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(BytesVisitor)
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::io::{self, Read};
use std::time::Duration;

use reqwest::header::{HeaderValue, CONNECTION};
use reqwest::{Client, ClientBuilder};

use self::error::{DownloadError, ErrorKind};
use failure::ResultExt;

#[derive(Clone, Debug)]
pub struct Url<'a> {
    url: Cow<'a, str>,
    max_kib: Option<usize>,
    timeout: Option<Duration>,
}

impl<'a> From<String> for Url<'a> {
    fn from(url: String) -> Self {
        Url {
            url: Cow::from(url),
            max_kib: None,
            timeout: None,
        }
    }
}

impl<'a> From<&'a str> for Url<'a> {
    fn from(url: &'a str) -> Self {
        Url {
            url: Cow::from(url),
            max_kib: None,
            timeout: None,
        }
    }
}

impl<'a> Url<'a> {
    pub fn max_kib(mut self, limit: usize) -> Self {
        self.max_kib = Some(limit);
        self
    }

    pub fn timeout(mut self, timeout: Duration) -> Self {
        self.timeout = Some(timeout);
        self
    }

    /// Downloads the file and converts it to a String.
    /// Any invalid bytes are converted to a replacement character.
    ///
    /// The error indicated either a failed download or
    /// that the limit set by max_kib() was reached.
    pub fn request(&self) -> Result<String, DownloadError> {
        let client = if let Some(timeout) = self.timeout {
            ClientBuilder::new().timeout(timeout).build().unwrap()
        } else {
            Client::new()
        };

        let mut response = client
            .get(self.url.as_ref())
            .header(CONNECTION, HeaderValue::from_static("close"))
            .send()
            .context(ErrorKind::Connection)?;

        // 100 kibibyte buffer
        let mut buf = [0; 100 * 1024];
        let mut written = 0;
        let mut bytes = Vec::new();

        // Read until we reach EOF or max_kib KiB
        loop {
            let len = match response.read(&mut buf) {
                Ok(0) => break,
                Ok(len) => len,
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                Err(e) => Err(e).context(ErrorKind::Read)?,
            };

            bytes.extend_from_slice(&buf[..len]);
            written += len;

            // Check if the file is too large to download
            if let Some(max_kib) = self.max_kib {
                if written > max_kib * 1024 {
                    Err(ErrorKind::DownloadLimit)?;
                }
            }
        }

        Ok(String::from_utf8_lossy(&bytes).into_owned())
    }

    pub fn as_str(&self) -> &str {
        &self.url
    }
}

pub mod error {
    use failure::Fail;
    use frippy_derive::Error;

    #[derive(Copy, Clone, Eq, PartialEq, Debug, Fail, Error)]
    #[error = "DownloadError"]
    pub enum ErrorKind {
        /// Connection Error
        #[fail(display = "A connection error has occured")]
        Connection,

        /// Read Error
        #[fail(display = "A read error has occured")]
        Read,

        /// Reached download limit error
        #[fail(display = "Reached download limit")]
        DownloadLimit,
    }
}
<commit_msg>Utils: Add Accept-Language header to requests<commit_after>use std::borrow::Cow;
use std::io::{self, Read};
use std::time::Duration;

use reqwest::header::{HeaderValue, ACCEPT_LANGUAGE, CONNECTION};
use reqwest::{Client, ClientBuilder};

use self::error::{DownloadError, ErrorKind};
use failure::ResultExt;

#[derive(Clone, Debug)]
pub struct Url<'a> {
    url: Cow<'a, str>,
    max_kib: Option<usize>,
    timeout: Option<Duration>,
}

impl<'a> From<String> for Url<'a> {
    fn from(url: String) -> Self {
        Url {
            url: Cow::from(url),
            max_kib: None,
            timeout: None,
        }
    }
}

impl<'a> From<&'a str> for Url<'a> {
    fn from(url: &'a str) -> Self {
        Url {
            url: Cow::from(url),
            max_kib: None,
            timeout: None,
        }
    }
}

impl<'a> Url<'a> {
    pub fn max_kib(mut self, limit: usize) -> Self {
        self.max_kib = Some(limit);
        self
    }

    pub fn timeout(mut self, timeout: Duration) -> Self {
        self.timeout = Some(timeout);
        self
    }

    /// Downloads the file and converts it to a String.
    /// Any invalid bytes are converted to a replacement character.
    ///
    /// The error indicated either a failed download or
    /// that the limit set by max_kib() was reached.
    pub fn request(&self) -> Result<String, DownloadError> {
        let client = if let Some(timeout) = self.timeout {
            ClientBuilder::new().timeout(timeout).build().unwrap()
        } else {
            Client::new()
        };

        let mut response = client
            .get(self.url.as_ref())
            .header(CONNECTION, HeaderValue::from_static("close"))
            .header(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.5"))
            .send()
            .context(ErrorKind::Connection)?;

        // 100 kibibyte buffer
        let mut buf = [0; 100 * 1024];
        let mut written = 0;
        let mut bytes = Vec::new();

        // Read until we reach EOF or max_kib KiB
        loop {
            let len = match response.read(&mut buf) {
                Ok(0) => break,
                Ok(len) => len,
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                Err(e) => Err(e).context(ErrorKind::Read)?,
            };

            bytes.extend_from_slice(&buf[..len]);
            written += len;

            // Check if the file is too large to download
            if let Some(max_kib) = self.max_kib {
                if written > max_kib * 1024 {
                    Err(ErrorKind::DownloadLimit)?;
                }
            }
        }

        Ok(String::from_utf8_lossy(&bytes).into_owned())
    }

    pub fn as_str(&self) -> &str {
        &self.url
    }
}

pub mod error {
    use failure::Fail;
    use frippy_derive::Error;

    #[derive(Copy, Clone, Eq, PartialEq, Debug, Fail, Error)]
    #[error = "DownloadError"]
    pub enum ErrorKind {
        /// Connection Error
        #[fail(display = "A connection error has occured")]
        Connection,

        /// Read Error
        #[fail(display = "A read error has occured")]
        Read,

        /// Reached download limit error
        #[fail(display = "Reached download limit")]
        DownloadLimit,
    }
}
<|endoftext|>