<commit_before>#![doc="Provides functions to create special matrices.
"]

// std imports
use std::num;

// local imports
use matrix::matrix::*;
use matrix::error::*;
use matrix::element::MatrixElt;

#[doc="Returns a hadamard matrix of size n x n

n must be a power of 2.
"]
pub fn hadamard(n : uint) -> Result<MatrixF64, MatrixError>{
    if !num::is_power_of_two(n){
        return Err(IsNotPowerOfTwo);
    }
    let mut m : MatrixF64 = Matrix::new(n, n);
    // Take the log of n with respect to 2.
    let order = n.trailing_zeros();
    // We are going to use Sylvester's construction
    // http://en.wikipedia.org/wiki/Hadamard_matrix

    // Let's fill the first level Hadamard matrix
    m.set(0, 0, 1.0);
    for  o in range(0, order){
        // We will construct four views.
        let size = num::pow(2u, o);
        // top left block
        let tl = m.view(0, 0, size, size);
        // top right block
        let mut tr = m.view(0, size, size, size);
        // bottom left block
        let mut bl = m.view(size, 0, size, size);
        // bottom right block
        let mut br = m.view(size, size, size, size);
        tr.copy_from(&tl);
        bl.copy_from(&tl);
        br.copy_scaled_from(&tl, -1.0);
    }
    Ok(m)
}

#[doc="Returns a matrix whose entries are picked up from
a range in column wise order.

# Remarks

Say you wish to create a matrix of 100 elements. If you
provide a range of 80 numbers, the first 80 entries in the
matrix will be filled by the numbers from the range. The
remaining 20 entries will be filled with zeros. On the
other hand, if you provide a range with more than 100 numbers,
then only the first 100 numbers will be used to fill the matrix
(off course in column major order). The remaining numbers
in the range will not be used. They will also not be generated.

# Examples

Constructing a 4x4 matrix of floating point numbers:

        use scirust::matrix::MatrixF64;
        use scirust::matrix::from_range;
        let start  = 0.0;
        let stop = 16.0;
        let m : MatrixF64 = from_range(4, 4, start, stop);
        for i in range(0, 16){
            let c = i >> 2;
            let r = i & 3;
            assert_eq!(m.get(r, c), i as f64);
        }

"]
pub fn from_range<T:MatrixElt+PartialOrd+Clone+ToPrimitive>(rows : uint, cols : uint,
    start : T, stop : T )-> Matrix<T> {
    let m : Matrix<T> = Matrix::from_iter(rows, cols, range(start, stop));
    m
}

#[doc="Returns a 64-bit floating point matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_f64(rows : uint, cols : uint,
    start : f64, stop : f64)->MatrixF64 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 8-bit signed integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_i8(rows : uint, cols : uint,
    start : i8, stop : i8)->MatrixI8 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 16-bit signed integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_i16(rows : uint, cols : uint,
    start : i16, stop : i16)->MatrixI16 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 32-bit signed integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_i32(rows : uint, cols : uint,
    start : i32, stop : i32)->MatrixI32 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 64-bit signed integer matrix whose entries are
picked up from a range in column wise order.

See from_range function  for further discussion.

# Examples

    use scirust::matrix::from_range_i64;

    let m = from_range_i64(4, 4, 0, 16);
    for i in range(0, 16){
        let c = i >> 2;
        let r = i & 3;
        assert_eq!(m.get(r, c), i as i64);
    }
"]
#[inline]
pub fn from_range_i64(rows : uint, cols : uint,
    start : i64, stop : i64)->MatrixI64 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 8-bit unsigned integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_u8(rows : uint, cols : uint,
    start : u8, stop : u8)->MatrixU8 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 16-bit unsigned integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_u16(rows : uint, cols : uint,
    start : u16, stop : u16)->MatrixU16 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 32-bit unsigned integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_u32(rows : uint, cols : uint,
    start : u32, stop : u32)->MatrixU32 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 64-bit unsigned integer matrix whose entries are
picked up from a range in column wise order.

See from_range function  for further discussion.

# Examples

    use scirust::matrix::from_range_u64;

    let m = from_range_u64(4, 4, 0, 16);
    for i in range(0, 16){
        let c = i >> 2;
        let r = i & 3;
        assert_eq!(m.get(r, c), i as u64);
    }
"]
#[inline]
pub fn from_range_u64(rows : uint, cols : uint,
    start : u64, stop : u64)->MatrixU64 {
    from_range(rows, cols, start, stop)
}

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

    #[test]
    fn test_hadamard(){
        let m = hadamard(1).unwrap();
        assert_eq!(m.num_cells(), 1);
        assert_eq!(m.get(0,0), 1.0);
        let m = hadamard(2).unwrap();
        assert_eq!(m.num_cells(), 4);
        assert_eq!(m.get(0,0), 1.0);
        assert_eq!(m.get(0,1), 1.0);
        assert_eq!(m.get(1,0), 1.0);
        assert_eq!(m.get(1,1), -1.0);
        let m = hadamard(4).unwrap();
        assert!(m.is_square());
    }

    #[test]
    fn test_range(){
        let m = from_range_i64(4, 4, 0, 16);
        for i in range(0, 16){
            let c = i >> 2;
            let r = i & 3;
            assert_eq!(m.get(r, c), i as i64);
        }
        let start  = 0.0;
        let stop = 16.0;
        let m : MatrixF64 = from_range(4, 4, start, stop);
        for i in range(0, 16){
            let c = i >> 2;
            let r = i & 3;
            assert_eq!(m.get(r, c), i as f64);
        }
        let m = from_range_f64(4, 4, start, stop);
        for i in range(0, 16){
            let c = i >> 2;
            let r = i & 3;
            assert_eq!(m.get(r, c), i as f64);
        }
    }
}
<commit_msg>Functions for creating matrices from slices. Now there is no more dependency on vectors.<commit_after>#![doc="Provides functions to create special matrices.
"]

// std imports
use std::num;

// local imports
use matrix::matrix::*;
use matrix::error::*;
use matrix::element::MatrixElt;

#[doc="Returns a hadamard matrix of size n x n

n must be a power of 2.
"]
pub fn hadamard(n : uint) -> Result<MatrixF64, MatrixError>{
    if !num::is_power_of_two(n){
        return Err(IsNotPowerOfTwo);
    }
    let mut m : MatrixF64 = Matrix::new(n, n);
    // Take the log of n with respect to 2.
    let order = n.trailing_zeros();
    // We are going to use Sylvester's construction
    // http://en.wikipedia.org/wiki/Hadamard_matrix

    // Let's fill the first level Hadamard matrix
    m.set(0, 0, 1.0);
    for  o in range(0, order){
        // We will construct four views.
        let size = num::pow(2u, o);
        // top left block
        let tl = m.view(0, 0, size, size);
        // top right block
        let mut tr = m.view(0, size, size, size);
        // bottom left block
        let mut bl = m.view(size, 0, size, size);
        // bottom right block
        let mut br = m.view(size, size, size, size);
        tr.copy_from(&tl);
        bl.copy_from(&tl);
        br.copy_scaled_from(&tl, -1.0);
    }
    Ok(m)
}

#[doc="Returns a matrix whose entries are picked up from
a range in column wise order.

# Remarks

Say you wish to create a matrix of 100 elements. If you
provide a range of 80 numbers, the first 80 entries in the
matrix will be filled by the numbers from the range. The
remaining 20 entries will be filled with zeros. On the
other hand, if you provide a range with more than 100 numbers,
then only the first 100 numbers will be used to fill the matrix
(off course in column major order). The remaining numbers
in the range will not be used. They will also not be generated.

# Examples

Constructing a 4x4 matrix of floating point numbers:

        use scirust::matrix::MatrixF64;
        use scirust::matrix::from_range;
        let start  = 0.0;
        let stop = 16.0;
        let m : MatrixF64 = from_range(4, 4, start, stop);
        for i in range(0, 16){
            let c = i >> 2;
            let r = i & 3;
            assert_eq!(m.get(r, c), i as f64);
        }

"]
pub fn from_range<T:MatrixElt+PartialOrd+Clone+ToPrimitive>(rows : uint, cols : uint,
    start : T, stop : T )-> Matrix<T> {
    let m : Matrix<T> = Matrix::from_iter(rows, cols, range(start, stop));
    m
}

#[doc="Returns a 64-bit floating point matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_f64(rows : uint, cols : uint,
    start : f64, stop : f64)->MatrixF64 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 8-bit signed integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_i8(rows : uint, cols : uint,
    start : i8, stop : i8)->MatrixI8 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 16-bit signed integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_i16(rows : uint, cols : uint,
    start : i16, stop : i16)->MatrixI16 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 32-bit signed integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_i32(rows : uint, cols : uint,
    start : i32, stop : i32)->MatrixI32 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 64-bit signed integer matrix whose entries are
picked up from a range in column wise order.

See from_range function  for further discussion.

# Examples

    use scirust::matrix::from_range_i64;

    let m = from_range_i64(4, 4, 0, 16);
    for i in range(0, 16){
        let c = i >> 2;
        let r = i & 3;
        assert_eq!(m.get(r, c), i as i64);
    }
"]
#[inline]
pub fn from_range_i64(rows : uint, cols : uint,
    start : i64, stop : i64)->MatrixI64 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 8-bit unsigned integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_u8(rows : uint, cols : uint,
    start : u8, stop : u8)->MatrixU8 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 16-bit unsigned integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_u16(rows : uint, cols : uint,
    start : u16, stop : u16)->MatrixU16 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 32-bit unsigned integer matrix whose entries are
picked up from a range in column wise order.
"]
#[inline]
pub fn from_range_u32(rows : uint, cols : uint,
    start : u32, stop : u32)->MatrixU32 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 64-bit unsigned integer matrix whose entries are
picked up from a range in column wise order.

See from_range function  for further discussion.

# Examples

    use scirust::matrix::from_range_u64;

    let m = from_range_u64(4, 4, 0, 16);
    for i in range(0, 16){
        let c = i >> 2;
        let r = i & 3;
        assert_eq!(m.get(r, c), i as u64);
    }
"]
#[inline]
pub fn from_range_u64(rows : uint, cols : uint,
    start : u64, stop : u64)->MatrixU64 {
    from_range(rows, cols, start, stop)
}

#[doc="Returns an 8-bit unsigned integer matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_u8(rows : uint, cols : uint, values: &[u8])->MatrixU8 {
    Matrix::from_slice(rows, cols, values)
}

#[doc="Returns a 16-bit unsigned integer matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_u16(rows : uint, cols : uint, values: &[u16])->MatrixU16 {
    Matrix::from_slice(rows, cols, values)
}

#[doc="Returns a 32-bit unsigned integer matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_u32(rows : uint, cols : uint, values: &[u32])->MatrixU32 {
    Matrix::from_slice(rows, cols, values)
}

#[doc="Returns a 64-bit unsigned integer matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_u64(rows : uint, cols : uint, values: &[u64])->MatrixU64 {
    Matrix::from_slice(rows, cols, values)
}

#[doc="Returns an 8-bit signed integer matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_i8(rows : uint, cols : uint, values: &[i8])->MatrixI8 {
    Matrix::from_slice(rows, cols, values)
}

#[doc="Returns a 16-bit signed integer matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_i16(rows : uint, cols : uint, values: &[i16])->MatrixI16 {
    Matrix::from_slice(rows, cols, values)
}

#[doc="Returns a 32-bit signed integer matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_i32(rows : uint, cols : uint, values: &[i32])->MatrixI32 {
    Matrix::from_slice(rows, cols, values)
}

#[doc="Returns a 64-bit signed integer matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_i64(rows : uint, cols : uint, values: &[i64])->MatrixI64 {
    Matrix::from_slice(rows, cols, values)
}

#[doc="Returns a 32-bit float matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_f32(rows : uint, cols : uint, values: &[f32])->MatrixF32 {
    Matrix::from_slice(rows, cols, values)
}

#[doc="Returns a 64-bit float matrix whose entries are
picked up from a slice in column wise order.
"]
#[inline]
pub fn matrix_f64(rows : uint, cols : uint, values: &[f64])->MatrixF64 {
    Matrix::from_slice(rows, cols, values)
}

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

    #[test]
    fn test_hadamard(){
        let m = hadamard(1).unwrap();
        assert_eq!(m.num_cells(), 1);
        assert_eq!(m.get(0,0), 1.0);
        let m = hadamard(2).unwrap();
        assert_eq!(m.num_cells(), 4);
        assert_eq!(m.get(0,0), 1.0);
        assert_eq!(m.get(0,1), 1.0);
        assert_eq!(m.get(1,0), 1.0);
        assert_eq!(m.get(1,1), -1.0);
        let m = hadamard(4).unwrap();
        assert!(m.is_square());
    }

    #[test]
    fn test_range(){
        let m = from_range_i64(4, 4, 0, 16);
        for i in range(0, 16){
            let c = i >> 2;
            let r = i & 3;
            assert_eq!(m.get(r, c), i as i64);
        }
        let start  = 0.0;
        let stop = 16.0;
        let m : MatrixF64 = from_range(4, 4, start, stop);
        for i in range(0, 16){
            let c = i >> 2;
            let r = i & 3;
            assert_eq!(m.get(r, c), i as f64);
        }
        let m = from_range_f64(4, 4, start, stop);
        for i in range(0, 16){
            let c = i >> 2;
            let r = i & 3;
            assert_eq!(m.get(r, c), i as f64);
        }
    }

    #[test]
    fn test_matrix_type_functions(){
        let m = matrix_u8(2,2, [1,2,3,4]);
        for i in range(0, 4){
            let c = i >> 1;
            let r = i & 1;
            assert_eq!(m.get(r, c), (i + 1) as u8);
        }
        let m = matrix_u16(2,2, [1,2,3,4]);
        for i in range(0, 4){
            let c = i >> 1;
            let r = i & 1;
            assert_eq!(m.get(r, c), (i + 1) as u16);
        }
        let m = matrix_u32(2,2, [1,2,3,4]);
        for i in range(0, 4){
            let c = i >> 1;
            let r = i & 1;
            assert_eq!(m.get(r, c), (i + 1) as u32);
        }
        let m = matrix_u64(2,2, [1,2,3,4]);
        for i in range(0, 4){
            let c = i >> 1;
            let r = i & 1;
            assert_eq!(m.get(r, c), (i + 1) as u64);
        }
        let m = matrix_i8(2,2, [1,2,3,4]);
        for i in range(0, 4){
            let c = i >> 1;
            let r = i & 1;
            assert_eq!(m.get(r, c), (i + 1) as i8);
        }
        let m = matrix_i16(2,2, [1,2,3,4]);
        for i in range(0, 4){
            let c = i >> 1;
            let r = i & 1;
            assert_eq!(m.get(r, c), (i + 1) as i16);
        }
        let m = matrix_i32(2,2, [1,2,3,4]);
        for i in range(0, 4){
            let c = i >> 1;
            let r = i & 1;
            assert_eq!(m.get(r, c), (i + 1) as i32);
        }
        let m = matrix_i64(2,2, [1,2,3,4]);
        for i in range(0, 4){
            let c = i >> 1;
            let r = i & 1;
            assert_eq!(m.get(r, c), (i + 1) as i64);
        }
        let m = matrix_f64(2,2, [1.0,2.0,3.0,4.0]);
        for i in range(0, 4){
            let c = i >> 1;
            let r = i & 1;
            assert_eq!(m.get(r, c), (i + 1) as f64);
        }
    }
}
<|endoftext|>


<commit_before>#![no_main]
extern crate libfuzzer_sys;
extern crate capnp;

use capnp::{serialize, message};

fn try_go(mut data: &[u8]) -> ::capnp::Result<()> {
    let orig_data = data;
    let message = serialize::read_message(&mut data, Default::default())?;
    assert!(orig_data.len() > data.len());
    let bytes_consumed = orig_data.len() - data.len();
    let maybe_is_canonical = message.is_canonical();
    let canonical_words = message.canonicalize()?;

    if let Ok(true) = maybe_is_canonical {
        assert_eq!(&orig_data[8..bytes_consumed], &canonical_words[..]);
    }

    let segments = &[&canonical_words[..]];
    let segment_array = message::SegmentArray::new(segments);
    let canonical_message = message::Reader::new(segment_array, Default::default());
    assert!(canonical_message.is_canonical()?);

    let canonical2_words = canonical_message.canonicalize()?;
    assert_eq!(canonical_words, canonical2_words);
    Ok(())
}

#[export_name="rust_fuzzer_test_input"]
pub extern fn go(data: &[u8]) {
    let _ = try_go(data);
}
<commit_msg>fix fuzzer<commit_after>#![no_main]
extern crate libfuzzer_sys;
extern crate capnp;

use capnp::{serialize, message};

fn try_go(mut data: &[u8]) -> ::capnp::Result<()> {
    let orig_data = data;
    let message = serialize::read_message(&mut data, Default::default())?;
    assert!(orig_data.len() > data.len());
    let bytes_consumed = orig_data.len() - data.len();
    let maybe_is_canonical = message.is_canonical();
    let canonical_words = message.canonicalize()?;

    if let Ok(true) = maybe_is_canonical {
        assert_eq!(&orig_data[8..bytes_consumed], capnp::Word::words_to_bytes(&canonical_words[..]));
    }

    let segments = &[capnp::Word::words_to_bytes(&canonical_words[..])];
    let segment_array = message::SegmentArray::new(segments);
    let canonical_message = message::Reader::new(segment_array, Default::default());
    assert!(canonical_message.is_canonical()?);

    let canonical2_words = canonical_message.canonicalize()?;
    assert_eq!(canonical_words, canonical2_words);
    Ok(())
}

#[export_name="rust_fuzzer_test_input"]
pub extern fn go(data: &[u8]) {
    let _ = try_go(data);
}
<|endoftext|>


<commit_before>//! Completion for associated items in a trait implementation.
//!
//! This module adds the completion items related to implementing associated
//! items within a `impl Trait for Struct` block. The current context node
//! must be within either a `FN`, `TYPE_ALIAS`, or `CONST` node
//! and an direct child of an `IMPL`.
//!
//! # Examples
//!
//! Considering the following trait `impl`:
//!
//! ```ignore
//! trait SomeTrait {
//!     fn foo();
//! }
//!
//! impl SomeTrait for () {
//!     fn f<|>
//! }
//! ```
//!
//! may result in the completion of the following method:
//!
//! ```ignore
//! # trait SomeTrait {
//! #    fn foo();
//! # }
//!
//! impl SomeTrait for () {
//!     fn foo() {}<|>
//! }
//! ```

use assists::utils::get_missing_assoc_items;
use hir::{self, HasAttrs, HasSource};
use syntax::{
    ast::{self, edit, Impl},
    AstNode, SyntaxKind, SyntaxNode, TextRange, T,
};
use text_edit::TextEdit;

use crate::{
    completion::{
        CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
    },
    display::function_declaration,
};

#[derive(Debug, PartialEq, Eq)]
enum ImplCompletionKind {
    All,
    Fn,
    TypeAlias,
    Const,
}

pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
    if let Some((kind, trigger, impl_def)) = completion_match(ctx) {
        get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| match item {
            hir::AssocItem::Function(fn_item)
                if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Fn =>
            {
                add_function_impl(&trigger, acc, ctx, fn_item)
            }
            hir::AssocItem::TypeAlias(type_item)
                if kind == ImplCompletionKind::All || kind == ImplCompletionKind::TypeAlias =>
            {
                add_type_alias_impl(&trigger, acc, ctx, type_item)
            }
            hir::AssocItem::Const(const_item)
                if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Const =>
            {
                add_const_impl(&trigger, acc, ctx, const_item)
            }
            _ => {}
        });
    }
}

fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> {
    let mut token = ctx.token.clone();
    // For keywork without name like `impl .. { fn <|> }`, the current position is inside
    // the whitespace token, which is outside `FN` syntax node.
    // We need to follow the previous token in this case.
    if token.kind() == SyntaxKind::WHITESPACE {
        token = token.prev_token()?;
    }

    let (kind, trigger, impl_def_offset) = token.ancestors().find_map(|p| match p.kind() {
        // `const` can be a modifier of an item, so the `const` token may be inside another item syntax node.
        // Eg. `impl .. { const <|> fn bar() .. }`
        SyntaxKind::FN | SyntaxKind::TYPE_ALIAS | SyntaxKind::CONST
            if token.kind() == SyntaxKind::CONST_KW =>
        {
            Some((ImplCompletionKind::Const, p, 2))
        }
        SyntaxKind::FN => Some((ImplCompletionKind::Fn, p, 2)),
        SyntaxKind::TYPE_ALIAS => Some((ImplCompletionKind::TypeAlias, p, 2)),
        SyntaxKind::CONST => Some((ImplCompletionKind::Const, p, 2)),
        // `impl .. { const <|> }` is parsed as:
        // IMPL
        //   ASSOC_ITEM_LIST
        //     ERROR
        //       CONST_KW <- token
        //     WHITESPACE <- ctx.token
        SyntaxKind::ERROR
            if p.first_token().map_or(false, |t| t.kind() == SyntaxKind::CONST_KW) =>
        {
            Some((ImplCompletionKind::Const, p, 2))
        }
        SyntaxKind::NAME_REF => Some((ImplCompletionKind::All, p, 5)),
        _ => None,
    })?;

    let impl_def = (0..impl_def_offset - 1)
        .try_fold(trigger.parent()?, |t, _| t.parent())
        .and_then(ast::Impl::cast)?;
    Some((kind, trigger, impl_def))
}

fn add_function_impl(
    fn_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    func: hir::Function,
) {
    let fn_name = func.name(ctx.db).to_string();

    let label = if func.params(ctx.db).is_empty() {
        format!("fn {}()", fn_name)
    } else {
        format!("fn {}(..)", fn_name)
    };

    let builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label)
        .lookup_by(fn_name)
        .set_documentation(func.docs(ctx.db));

    let completion_kind = if func.self_param(ctx.db).is_some() {
        CompletionItemKind::Method
    } else {
        CompletionItemKind::Function
    };
    let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end());

    let function_decl = function_declaration(&func.source(ctx.db).value);
    match ctx.config.snippet_cap {
        Some(cap) => {
            let snippet = format!("{} {{\n    $0\n}}", function_decl);
            builder.snippet_edit(cap, TextEdit::replace(range, snippet))
        }
        None => {
            let header = format!("{} {{", function_decl);
            builder.text_edit(TextEdit::replace(range, header))
        }
    }
    .kind(completion_kind)
    .add_to(acc);
}

fn add_type_alias_impl(
    type_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    type_alias: hir::TypeAlias,
) {
    let alias_name = type_alias.name(ctx.db).to_string();

    let snippet = format!("type {} = ", alias_name);

    let range = TextRange::new(type_def_node.text_range().start(), ctx.source_range().end());

    CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
        .text_edit(TextEdit::replace(range, snippet))
        .lookup_by(alias_name)
        .kind(CompletionItemKind::TypeAlias)
        .set_documentation(type_alias.docs(ctx.db))
        .add_to(acc);
}

fn add_const_impl(
    const_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    const_: hir::Const,
) {
    let const_name = const_.name(ctx.db).map(|n| n.to_string());

    if let Some(const_name) = const_name {
        let snippet = make_const_compl_syntax(&const_.source(ctx.db).value);

        let range = TextRange::new(const_def_node.text_range().start(), ctx.source_range().end());

        CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
            .text_edit(TextEdit::replace(range, snippet))
            .lookup_by(const_name)
            .kind(CompletionItemKind::Const)
            .set_documentation(const_.docs(ctx.db))
            .add_to(acc);
    }
}

fn make_const_compl_syntax(const_: &ast::Const) -> String {
    let const_ = edit::remove_attrs_and_docs(const_);

    let const_start = const_.syntax().text_range().start();
    let const_end = const_.syntax().text_range().end();

    let start =
        const_.syntax().first_child_or_token().map_or(const_start, |f| f.text_range().start());

    let end = const_
        .syntax()
        .children_with_tokens()
        .find(|s| s.kind() == T![;] || s.kind() == T![=])
        .map_or(const_end, |f| f.text_range().start());

    let len = end - start;
    let range = TextRange::new(0.into(), len);

    let syntax = const_.syntax().text().slice(range).to_string();

    format!("{} = ", syntax.trim_end())
}

#[cfg(test)]
mod tests {
    use expect_test::{expect, Expect};

    use crate::completion::{
        test_utils::{check_edit, completion_list},
        CompletionKind,
    };

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Magic);
        expect.assert_eq(&actual)
    }

    #[test]
    fn name_ref_function_type_const() {
        check(
            r#"
trait Test {
    type TestType;
    const TEST_CONST: u16;
    fn test();
}
struct T;

impl Test for T {
    t<|>
}
"#,
            expect![["
ct const TEST_CONST: u16 = \n\
fn fn test()
ta type TestType = \n\
            "]],
        );
    }

    #[test]
    fn no_nested_fn_completions() {
        check(
            r"
trait Test {
    fn test();
    fn test2();
}
struct T;

impl Test for T {
    fn test() {
        t<|>
    }
}
",
            expect![[""]],
        );
    }

    #[test]
    fn name_ref_single_function() {
        check_edit(
            "test",
            r#"
trait Test {
    fn test();
}
struct T;

impl Test for T {
    t<|>
}
"#,
            r#"
trait Test {
    fn test();
}
struct T;

impl Test for T {
    fn test() {
    $0
}
}
"#,
        );
    }

    #[test]
    fn single_function() {
        check_edit(
            "test",
            r#"
trait Test {
    fn test();
}
struct T;

impl Test for T {
    fn t<|>
}
"#,
            r#"
trait Test {
    fn test();
}
struct T;

impl Test for T {
    fn test() {
    $0
}
}
"#,
        );
    }

    #[test]
    fn hide_implemented_fn() {
        check(
            r#"
trait Test {
    fn foo();
    fn foo_bar();
}
struct T;

impl Test for T {
    fn foo() {}
    fn f<|>
}
"#,
            expect![[r#"
                fn fn foo_bar()
            "#]],
        );
    }

    #[test]
    fn generic_fn() {
        check_edit(
            "foo",
            r#"
trait Test {
    fn foo<T>();
}
struct T;

impl Test for T {
    fn f<|>
}
"#,
            r#"
trait Test {
    fn foo<T>();
}
struct T;

impl Test for T {
    fn foo<T>() {
    $0
}
}
"#,
        );
        check_edit(
            "foo",
            r#"
trait Test {
    fn foo<T>() where T: Into<String>;
}
struct T;

impl Test for T {
    fn f<|>
}
"#,
            r#"
trait Test {
    fn foo<T>() where T: Into<String>;
}
struct T;

impl Test for T {
    fn foo<T>()
where T: Into<String> {
    $0
}
}
"#,
        );
    }

    #[test]
    fn associated_type() {
        check_edit(
            "SomeType",
            r#"
trait Test {
    type SomeType;
}

impl Test for () {
    type S<|>
}
"#,
            "
trait Test {
    type SomeType;
}

impl Test for () {
    type SomeType = \n\
}
",
        );
    }

    #[test]
    fn associated_const() {
        check_edit(
            "SOME_CONST",
            r#"
trait Test {
    const SOME_CONST: u16;
}

impl Test for () {
    const S<|>
}
"#,
            "
trait Test {
    const SOME_CONST: u16;
}

impl Test for () {
    const SOME_CONST: u16 = \n\
}
",
        );

        check_edit(
            "SOME_CONST",
            r#"
trait Test {
    const SOME_CONST: u16 = 92;
}

impl Test for () {
    const S<|>
}
"#,
            "
trait Test {
    const SOME_CONST: u16 = 92;
}

impl Test for () {
    const SOME_CONST: u16 = \n\
}
",
        );
    }

    #[test]
    fn complete_without_name() {
        let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| {
            println!(
                "completion='{}', hint='{}', next_sibling='{}'",
                completion, hint, next_sibling
            );

            check_edit(
                completion,
                &format!(
                    r#"
trait Test {{
    type Foo;
    const CONST: u16;
    fn bar();
}}
struct T;

impl Test for T {{
    {}
    {}
}}
"#,
                    hint, next_sibling
                ),
                &format!(
                    r#"
trait Test {{
    type Foo;
    const CONST: u16;
    fn bar();
}}
struct T;

impl Test for T {{
    {}
    {}
}}
"#,
                    completed, next_sibling
                ),
            )
        };

        // Enumerate some possible next siblings.
        for next_sibling in &[
            "",
            "fn other_fn() {}", // `const <|> fn` -> `const fn`
            "type OtherType = i32;",
            "const OTHER_CONST: i32 = 0;",
            "async fn other_fn() {}",
            "unsafe fn other_fn() {}",
            "default fn other_fn() {}",
            "default type OtherType = i32;",
            "default const OTHER_CONST: i32 = 0;",
        ] {
            test("bar", "fn <|>", "fn bar() {\n    $0\n}", next_sibling);
            test("Foo", "type <|>", "type Foo = ", next_sibling);
            test("CONST", "const <|>", "const CONST: u16 = ", next_sibling);
        }
    }
}
<commit_msg>Avoid checking all ancestors and fix mis-completion<commit_after>//! Completion for associated items in a trait implementation.
//!
//! This module adds the completion items related to implementing associated
//! items within a `impl Trait for Struct` block. The current context node
//! must be within either a `FN`, `TYPE_ALIAS`, or `CONST` node
//! and an direct child of an `IMPL`.
//!
//! # Examples
//!
//! Considering the following trait `impl`:
//!
//! ```ignore
//! trait SomeTrait {
//!     fn foo();
//! }
//!
//! impl SomeTrait for () {
//!     fn f<|>
//! }
//! ```
//!
//! may result in the completion of the following method:
//!
//! ```ignore
//! # trait SomeTrait {
//! #    fn foo();
//! # }
//!
//! impl SomeTrait for () {
//!     fn foo() {}<|>
//! }
//! ```

use assists::utils::get_missing_assoc_items;
use hir::{self, HasAttrs, HasSource};
use syntax::{
    ast::{self, edit, Impl},
    AstNode, SyntaxKind, SyntaxNode, TextRange, T,
};
use text_edit::TextEdit;

use crate::{
    completion::{
        CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
    },
    display::function_declaration,
};

#[derive(Debug, PartialEq, Eq)]
enum ImplCompletionKind {
    All,
    Fn,
    TypeAlias,
    Const,
}

pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
    if let Some((kind, trigger, impl_def)) = completion_match(ctx) {
        get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| match item {
            hir::AssocItem::Function(fn_item)
                if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Fn =>
            {
                add_function_impl(&trigger, acc, ctx, fn_item)
            }
            hir::AssocItem::TypeAlias(type_item)
                if kind == ImplCompletionKind::All || kind == ImplCompletionKind::TypeAlias =>
            {
                add_type_alias_impl(&trigger, acc, ctx, type_item)
            }
            hir::AssocItem::Const(const_item)
                if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Const =>
            {
                add_const_impl(&trigger, acc, ctx, const_item)
            }
            _ => {}
        });
    }
}

fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> {
    let mut token = ctx.token.clone();
    // For keywork without name like `impl .. { fn <|> }`, the current position is inside
    // the whitespace token, which is outside `FN` syntax node.
    // We need to follow the previous token in this case.
    if token.kind() == SyntaxKind::WHITESPACE {
        token = token.prev_token()?;
    }

    let impl_item_offset = match token.kind() {
        // `impl .. { const <|> }`
        // ERROR      0
        //   CONST_KW <- *
        SyntaxKind::CONST_KW => 0,
        // `impl .. { fn/type <|> }`
        // FN/TYPE_ALIAS  0
        //   FN_KW        <- *
        SyntaxKind::FN_KW | SyntaxKind::TYPE_KW => 0,
        // `impl .. { fn/type/const foo<|> }`
        // FN/TYPE_ALIAS/CONST  1
        //  NAME                0
        //    IDENT             <- *
        SyntaxKind::IDENT if token.parent().kind() == SyntaxKind::NAME => 1,
        // `impl .. { foo<|> }`
        // MACRO_CALL       3
        //  PATH            2
        //    PATH_SEGMENT  1
        //      NAME_REF    0
        //        IDENT     <- *
        SyntaxKind::IDENT if token.parent().kind() == SyntaxKind::NAME_REF => 3,
        _ => return None,
    };

    let impl_item = token.ancestors().nth(impl_item_offset)?;
    // Must directly belong to an impl block.
    // IMPL
    //   ASSOC_ITEM_LIST
    //     <item>
    let impl_def = ast::Impl::cast(impl_item.parent()?.parent()?)?;
    let kind = match impl_item.kind() {
        // `impl ... { const <|> fn/type/const }`
        _ if token.kind() == SyntaxKind::CONST_KW => ImplCompletionKind::Const,
        SyntaxKind::CONST | SyntaxKind::ERROR => ImplCompletionKind::Const,
        SyntaxKind::TYPE_ALIAS => ImplCompletionKind::TypeAlias,
        SyntaxKind::FN => ImplCompletionKind::Fn,
        SyntaxKind::MACRO_CALL => ImplCompletionKind::All,
        _ => return None,
    };
    Some((kind, impl_item, impl_def))
}

fn add_function_impl(
    fn_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    func: hir::Function,
) {
    let fn_name = func.name(ctx.db).to_string();

    let label = if func.params(ctx.db).is_empty() {
        format!("fn {}()", fn_name)
    } else {
        format!("fn {}(..)", fn_name)
    };

    let builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label)
        .lookup_by(fn_name)
        .set_documentation(func.docs(ctx.db));

    let completion_kind = if func.self_param(ctx.db).is_some() {
        CompletionItemKind::Method
    } else {
        CompletionItemKind::Function
    };
    let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end());

    let function_decl = function_declaration(&func.source(ctx.db).value);
    match ctx.config.snippet_cap {
        Some(cap) => {
            let snippet = format!("{} {{\n    $0\n}}", function_decl);
            builder.snippet_edit(cap, TextEdit::replace(range, snippet))
        }
        None => {
            let header = format!("{} {{", function_decl);
            builder.text_edit(TextEdit::replace(range, header))
        }
    }
    .kind(completion_kind)
    .add_to(acc);
}

fn add_type_alias_impl(
    type_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    type_alias: hir::TypeAlias,
) {
    let alias_name = type_alias.name(ctx.db).to_string();

    let snippet = format!("type {} = ", alias_name);

    let range = TextRange::new(type_def_node.text_range().start(), ctx.source_range().end());

    CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
        .text_edit(TextEdit::replace(range, snippet))
        .lookup_by(alias_name)
        .kind(CompletionItemKind::TypeAlias)
        .set_documentation(type_alias.docs(ctx.db))
        .add_to(acc);
}

fn add_const_impl(
    const_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    const_: hir::Const,
) {
    let const_name = const_.name(ctx.db).map(|n| n.to_string());

    if let Some(const_name) = const_name {
        let snippet = make_const_compl_syntax(&const_.source(ctx.db).value);

        let range = TextRange::new(const_def_node.text_range().start(), ctx.source_range().end());

        CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
            .text_edit(TextEdit::replace(range, snippet))
            .lookup_by(const_name)
            .kind(CompletionItemKind::Const)
            .set_documentation(const_.docs(ctx.db))
            .add_to(acc);
    }
}

fn make_const_compl_syntax(const_: &ast::Const) -> String {
    let const_ = edit::remove_attrs_and_docs(const_);

    let const_start = const_.syntax().text_range().start();
    let const_end = const_.syntax().text_range().end();

    let start =
        const_.syntax().first_child_or_token().map_or(const_start, |f| f.text_range().start());

    let end = const_
        .syntax()
        .children_with_tokens()
        .find(|s| s.kind() == T![;] || s.kind() == T![=])
        .map_or(const_end, |f| f.text_range().start());

    let len = end - start;
    let range = TextRange::new(0.into(), len);

    let syntax = const_.syntax().text().slice(range).to_string();

    format!("{} = ", syntax.trim_end())
}

#[cfg(test)]
mod tests {
    use expect_test::{expect, Expect};

    use crate::completion::{
        test_utils::{check_edit, completion_list},
        CompletionKind,
    };

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Magic);
        expect.assert_eq(&actual)
    }

    #[test]
    fn name_ref_function_type_const() {
        check(
            r#"
trait Test {
    type TestType;
    const TEST_CONST: u16;
    fn test();
}
struct T;

impl Test for T {
    t<|>
}
"#,
            expect![["
ct const TEST_CONST: u16 = \n\
fn fn test()
ta type TestType = \n\
            "]],
        );
    }

    #[test]
    fn no_completion_inside_fn() {
        check(
            r"
trait Test { fn test(); fn test2(); }
struct T;

impl Test for T {
    fn test() {
        t<|>
    }
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { fn test(); fn test2(); }
struct T;

impl Test for T {
    fn test() {
        fn t<|>
    }
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { fn test(); fn test2(); }
struct T;

impl Test for T {
    fn test() {
        fn <|>
    }
}
",
            expect![[""]],
        );

        // https://github.com/rust-analyzer/rust-analyzer/pull/5976#issuecomment-692332191
        check(
            r"
trait Test { fn test(); fn test2(); }
struct T;

impl Test for T {
    fn test() {
        foo.<|>
    }
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { fn test(_: i32); fn test2(); }
struct T;

impl Test for T {
    fn test(t<|>)
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { fn test(_: fn()); fn test2(); }
struct T;

impl Test for T {
    fn test(f: fn <|>)
}
",
            expect![[""]],
        );
    }

    #[test]
    fn no_completion_inside_const() {
        check(
            r"
trait Test { const TEST: fn(); const TEST2: u32; type Test; fn test(); }
struct T;

impl Test for T {
    const TEST: fn <|>
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
struct T;

impl Test for T {
    const TEST: T<|>
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
struct T;

impl Test for T {
    const TEST: u32 = f<|>
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
struct T;

impl Test for T {
    const TEST: u32 = {
        t<|>
    };
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
struct T;

impl Test for T {
    const TEST: u32 = {
        fn <|>
    };
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
struct T;

impl Test for T {
    const TEST: u32 = {
        fn t<|>
    };
}
",
            expect![[""]],
        );
    }

    #[test]
    fn no_completion_inside_type() {
        check(
            r"
trait Test { type Test; type Test2; fn test(); }
struct T;

impl Test for T {
    type Test = T<|>;
}
",
            expect![[""]],
        );

        check(
            r"
trait Test { type Test; type Test2; fn test(); }
struct T;

impl Test for T {
    type Test = fn <|>;
}
",
            expect![[""]],
        );
    }

    #[test]
    fn name_ref_single_function() {
        check_edit(
            "test",
            r#"
trait Test {
    fn test();
}
struct T;

impl Test for T {
    t<|>
}
"#,
            r#"
trait Test {
    fn test();
}
struct T;

impl Test for T {
    fn test() {
    $0
}
}
"#,
        );
    }

    #[test]
    fn single_function() {
        check_edit(
            "test",
            r#"
trait Test {
    fn test();
}
struct T;

impl Test for T {
    fn t<|>
}
"#,
            r#"
trait Test {
    fn test();
}
struct T;

impl Test for T {
    fn test() {
    $0
}
}
"#,
        );
    }

    #[test]
    fn hide_implemented_fn() {
        check(
            r#"
trait Test {
    fn foo();
    fn foo_bar();
}
struct T;

impl Test for T {
    fn foo() {}
    fn f<|>
}
"#,
            expect![[r#"
                fn fn foo_bar()
            "#]],
        );
    }

    #[test]
    fn generic_fn() {
        check_edit(
            "foo",
            r#"
trait Test {
    fn foo<T>();
}
struct T;

impl Test for T {
    fn f<|>
}
"#,
            r#"
trait Test {
    fn foo<T>();
}
struct T;

impl Test for T {
    fn foo<T>() {
    $0
}
}
"#,
        );
        check_edit(
            "foo",
            r#"
trait Test {
    fn foo<T>() where T: Into<String>;
}
struct T;

impl Test for T {
    fn f<|>
}
"#,
            r#"
trait Test {
    fn foo<T>() where T: Into<String>;
}
struct T;

impl Test for T {
    fn foo<T>()
where T: Into<String> {
    $0
}
}
"#,
        );
    }

    #[test]
    fn associated_type() {
        check_edit(
            "SomeType",
            r#"
trait Test {
    type SomeType;
}

impl Test for () {
    type S<|>
}
"#,
            "
trait Test {
    type SomeType;
}

impl Test for () {
    type SomeType = \n\
}
",
        );
    }

    #[test]
    fn associated_const() {
        check_edit(
            "SOME_CONST",
            r#"
trait Test {
    const SOME_CONST: u16;
}

impl Test for () {
    const S<|>
}
"#,
            "
trait Test {
    const SOME_CONST: u16;
}

impl Test for () {
    const SOME_CONST: u16 = \n\
}
",
        );

        check_edit(
            "SOME_CONST",
            r#"
trait Test {
    const SOME_CONST: u16 = 92;
}

impl Test for () {
    const S<|>
}
"#,
            "
trait Test {
    const SOME_CONST: u16 = 92;
}

impl Test for () {
    const SOME_CONST: u16 = \n\
}
",
        );
    }

    #[test]
    fn complete_without_name() {
        let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| {
            println!(
                "completion='{}', hint='{}', next_sibling='{}'",
                completion, hint, next_sibling
            );

            check_edit(
                completion,
                &format!(
                    r#"
trait Test {{
    type Foo;
    const CONST: u16;
    fn bar();
}}
struct T;

impl Test for T {{
    {}
    {}
}}
"#,
                    hint, next_sibling
                ),
                &format!(
                    r#"
trait Test {{
    type Foo;
    const CONST: u16;
    fn bar();
}}
struct T;

impl Test for T {{
    {}
    {}
}}
"#,
                    completed, next_sibling
                ),
            )
        };

        // Enumerate some possible next siblings.
        for next_sibling in &[
            "",
            "fn other_fn() {}", // `const <|> fn` -> `const fn`
            "type OtherType = i32;",
            "const OTHER_CONST: i32 = 0;",
            "async fn other_fn() {}",
            "unsafe fn other_fn() {}",
            "default fn other_fn() {}",
            "default type OtherType = i32;",
            "default const OTHER_CONST: i32 = 0;",
        ] {
            test("bar", "fn <|>", "fn bar() {\n    $0\n}", next_sibling);
            test("Foo", "type <|>", "type Foo = ", next_sibling);
            test("CONST", "const <|>", "const CONST: u16 = ", next_sibling);
        }
    }
}
<|endoftext|>


<commit_before>use crate::symbol::{sym, Symbol};
use std::fmt;
use std::str::FromStr;

use rustc_macros::HashStable_Generic;

/// The edition of the compiler. (See [RFC 2052](https://github.com/rust-lang/rfcs/blob/master/text/2052-epochs.md).)
#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, Encodable, Decodable, Eq)]
#[derive(HashStable_Generic)]
pub enum Edition {
    // When adding new editions, be sure to do the following:
    //
    // - update the `ALL_EDITIONS` const
    // - update the `EDITION_NAME_LIST` const
    // - add a `rust_####()` function to the session
    // - update the enum in Cargo's sources as well
    //
    // Editions *must* be kept in order, oldest to newest.
    /// The 2015 edition
    Edition2015,
    /// The 2018 edition
    Edition2018,
    /// The 2021 edition
    Edition2021,
}

// Must be in order from oldest to newest.
pub const ALL_EDITIONS: &[Edition] =
    &[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021];

pub const EDITION_NAME_LIST: &str = "2015|2018|2021";

pub const DEFAULT_EDITION: Edition = Edition::Edition2015;

pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2018;

impl fmt::Display for Edition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match *self {
            Edition::Edition2015 => "2015",
            Edition::Edition2018 => "2018",
            Edition::Edition2021 => "2021",
        };
        write!(f, "{}", s)
    }
}

impl Edition {
    pub fn lint_name(&self) -> &'static str {
        match *self {
            Edition::Edition2015 => "rust_2015_compatibility",
            Edition::Edition2018 => "rust_2018_compatibility",
            Edition::Edition2021 => "rust_2021_compatibility",
        }
    }

    pub fn feature_name(&self) -> Symbol {
        match *self {
            Edition::Edition2015 => sym::rust_2015_preview,
            Edition::Edition2018 => sym::rust_2018_preview,
            Edition::Edition2021 => sym::rust_2021_preview,
        }
    }

    pub fn is_stable(&self) -> bool {
        match *self {
            Edition::Edition2015 => true,
            Edition::Edition2018 => true,
            Edition::Edition2021 => true,
        }
    }
}

impl FromStr for Edition {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, ()> {
        match s {
            "2015" => Ok(Edition::Edition2015),
            "2018" => Ok(Edition::Edition2018),
            "2021" => Ok(Edition::Edition2021),
            _ => Err(()),
        }
    }
}
<commit_msg>Update LATEST_STABLE_EDITION to 2021.<commit_after>use crate::symbol::{sym, Symbol};
use std::fmt;
use std::str::FromStr;

use rustc_macros::HashStable_Generic;

/// The edition of the compiler. (See [RFC 2052](https://github.com/rust-lang/rfcs/blob/master/text/2052-epochs.md).)
#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, Encodable, Decodable, Eq)]
#[derive(HashStable_Generic)]
pub enum Edition {
    // When adding new editions, be sure to do the following:
    //
    // - update the `ALL_EDITIONS` const
    // - update the `EDITION_NAME_LIST` const
    // - add a `rust_####()` function to the session
    // - update the enum in Cargo's sources as well
    //
    // Editions *must* be kept in order, oldest to newest.
    /// The 2015 edition
    Edition2015,
    /// The 2018 edition
    Edition2018,
    /// The 2021 edition
    Edition2021,
}

// Must be in order from oldest to newest.
pub const ALL_EDITIONS: &[Edition] =
    &[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021];

pub const EDITION_NAME_LIST: &str = "2015|2018|2021";

pub const DEFAULT_EDITION: Edition = Edition::Edition2015;

pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2021;

impl fmt::Display for Edition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match *self {
            Edition::Edition2015 => "2015",
            Edition::Edition2018 => "2018",
            Edition::Edition2021 => "2021",
        };
        write!(f, "{}", s)
    }
}

impl Edition {
    pub fn lint_name(&self) -> &'static str {
        match *self {
            Edition::Edition2015 => "rust_2015_compatibility",
            Edition::Edition2018 => "rust_2018_compatibility",
            Edition::Edition2021 => "rust_2021_compatibility",
        }
    }

    pub fn feature_name(&self) -> Symbol {
        match *self {
            Edition::Edition2015 => sym::rust_2015_preview,
            Edition::Edition2018 => sym::rust_2018_preview,
            Edition::Edition2021 => sym::rust_2021_preview,
        }
    }

    pub fn is_stable(&self) -> bool {
        match *self {
            Edition::Edition2015 => true,
            Edition::Edition2018 => true,
            Edition::Edition2021 => true,
        }
    }
}

impl FromStr for Edition {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, ()> {
        match s {
            "2015" => Ok(Edition::Edition2015),
            "2018" => Ok(Edition::Edition2018),
            "2021" => Ok(Edition::Edition2021),
            _ => Err(()),
        }
    }
}
<|endoftext|>


<commit_before>
#![allow(unused_variables)]
#![allow(dead_code)]

/// Basic structure of a Monitor (aka Server App, aka wtttttt)
///
/// Monitors are designed so that the FoxBox can offer a simple
/// IFTTT-style Web UX to let users write their own scripts. More
/// complex monitors can installed from the web from a master device
/// (i.e. the user's cellphone or smart tv).

use dependencies::{DeviceKind, InputCapability, OutputCapability, Device, Range, Watcher, Witness};

use std::time::Duration;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;

extern crate rustc_serialize;
use self::rustc_serialize::json::Json;

extern crate itertools;
use self::itertools::Zip;

/// A Monitor Application, i.e. an application (or a component of an
/// application) executed on the server.
///
/// Monitor applications are typically used for triggering an action
/// in reaction to an event: changing temperature when night falls,
/// ringing an alarm when a door is opened, etc.
///
/// Monitor applications are installed from a paired device. They may
/// either be part of a broader application (which can install them
/// through a web/REST API) or live on their own.
#[derive(Clone)]
struct MonitorApp {
    metadata: (), // FIXME: Authorizations, author, description, update url, version, ...

    /// `true` if the app is on, `false` otherwise.
    is_active: bool,

    /// Monitor applications have sets of requirements (e.g. "I need a
    /// camera"), which are allocated to actual resources through the
    /// UX. Re-allocating resources may be requested by the user, the
    /// foxbox, or an application, e.g. when replacing a device or
    /// upgrading the app.
    ///
    /// The position in the vector is important, as it is used to
    /// represent the instances of resources in the script.
    ///
    /// FIXME: Turn this `Vec` (and others) into a data structure in
    /// which this indexing property is built-in.
    requirements: Vec<Named<Requirement>>,

    /// For each requirement, the resources actually allocated to
    /// match the requirements. This may be 1 or more individual
    /// devices.
    ///
    /// Allocations can be done in several ways:
    ///
    /// - when entering the script through a UX (either the script or
    ///   the UX can suggest allocations);
    /// - when installing an application with a web front-end.
    allocations: Vec<Vec<Named<Arc<Device>>>>,

    code: Vec<Trigger>,

    is_running: bool,
}

impl<'a> MonitorApp {
/*
    Ideally, I'd like something along these lines.
    But, as rustc kindly pointed out to me, that's pretty much unsafe.

    fn iter_state_index(&'a self) -> Box<Iterator<Item=InputIndex> + 'a>
    {
        Box::new(
            Zip::new((&self.requirements, &self.allocations, 0..)).
                flat_map(|(req, allocation, allocation_index)| {
                    let allocation_index_clone = allocation_index.clone();
                    Zip::new((allocation, 0..)).
                        flat_map(|(individual_device, individual_device_index)| {
                            Zip::new((&req.data.inputs, 0..)).
                                map(|(_, individual_input_index)| {
                                    InputIndex {
                                        allocation: allocation_index_clone,
                                        device: individual_device_index,
                                        input: individual_input_index
                                    }
                                })
                        })
                }))
}
     */
    fn iter_state_index(&'a self) -> Vec<InputIndex>
    {
        let mut vec = Vec::new();
        for (req, allocation, allocation_index) in Zip::new((&self.requirements, &self.allocations, 0..)) {
            for (individual_device, individual_device_index) in Zip::new((allocation, 0..)) {
                for (input, individual_input_index) in Zip::new((&req.data.inputs, 0..)) {
                    vec.push(InputIndex {
                        allocation: allocation_index,
                        device: individual_device_index,
                        input: individual_input_index
                    })
                }
            }
        }
        vec
    }

    fn get_individual_device(&self, index: &InputIndex) -> Arc<Device> {
        self.allocations[index.allocation][index.device].data.clone()
    }

    fn get_input(&self, index: &InputIndex) -> InputCapability {
        self.requirements[index.allocation].data.inputs[index.input].data.clone()
    }
}

struct InputIndex {
    allocation: usize,
    device: usize,
    input: usize,
}

struct ConditionState {
    are_conditions_met: bool
}

type InputState = Vec<Vec<Vec<Option<Json>>>>;
struct MonitorTaskState {
    // Invariant: len() is the same as that of app.code
    trigger_condition_state: Vec<ConditionState>,

    /// For each device set allocated, for each individual device
    /// allocated, for each input watched by the app, the latest state
    /// received.
    // Invariant: outer len() is the same as that of self.requirements.
    // Invariant: inner len() is the same as number of input devices bound
    // to the corresponding requirement. May be empty.
    input_state: InputState,

    witnesses: Vec<Witness>,

    app: MonitorApp,
}
impl MonitorTaskState {
    fn set_state(&mut self, index: &InputIndex, value: Option<Json>) {
        self.input_state[index.allocation][index.device][index.input] = value;
    }
}

struct MonitorComm {
    tx: Sender<MonitorOp>,
    rx: Receiver<MonitorOp>,
}
struct MonitorTask {
    state: MonitorTaskState,
    comm: MonitorComm,
}

impl MonitorTask {
    fn new(app: MonitorApp) -> Self {
        // Initialize condition state.
        let mut trigger_condition_state = Vec::with_capacity(app.code.len());
        for _ in &app.code {
            trigger_condition_state.push(ConditionState {
                are_conditions_met: false,
            });
        }
        assert_eq!(trigger_condition_state.len(), app.code.len());

        // Initialize input state.
        let mut full_input_state = Vec::with_capacity(app.requirements.len());
        for (req, allocation) in app.requirements.iter().zip(&app.allocations) {

            // State for this allocation. A single allocation may map
            // to a number of inputs (e.g. "all fire alarms").
            let mut allocation_state = Vec::with_capacity(allocation.len());
            for individual_device in allocation {
                let mut individual_device_state = Vec::with_capacity(req.data.inputs.len());
                for _ in 0 .. req.data.inputs.len() {
                    individual_device_state.push(None);
                }
                allocation_state.push(individual_device_state);
            }
            assert_eq!(allocation_state.len(), allocation.len());
            full_input_state.push(allocation_state);
        }
        assert_eq!(full_input_state.len(), app.requirements.len());

        // Start watching
        let mut watcher = Watcher::new();
        let mut witnesses = Vec::new();
        let (tx, rx) = channel();

        for state_index in app.iter_state_index() {
            // FIXME: We currently use `Range::any()` for simplicity.
            // However, in most cases, we should be able to look inside
            // the condition to build a better `Range`.
            witnesses.push(
                watcher.add(
                    &app.get_individual_device(&state_index), // FIXME: Implement
                    &app.get_input(&state_index), // FIXME: Implement
                    &Range::any(),
                    |data| {
                        let _ = tx.send(MonitorOp::Update {
                            data: data,
                            index: state_index,
                        });
                        // Ignore errors. If the thread is shutting down, it's ok to lose messages.
                    }));
        }

        /*
        for (req, allocation, allocation_state, allocation_index) in Zip::new((&app.requirements, &app.allocations, &full_input_state, 0..)) {
            for (individual_device, individual_device_state, individual_device_index) in Zip::new((allocation, allocation_state, 0..)) {
                for (input, individual_input_state, individual_input_index) in Zip::new((&req.data.inputs, individual_device_state, 0..)) {
                    // FIXME: We currently use `Range::any()` for simplicity.
                    // However, in most cases, we should be able to look inside
                    // the condition to build a better `Range`.
                    witnesses.push(
                        watcher.add(
                            &individual_device.data,
                            &input.data,
                            &Range::any(),
                            |data| {
                                let _ = tx.send(MonitorOp::Update {
                                    data: data,
                                    allocation_index: allocation_index,
                                    individual_device_index: individual_device_index,
                                    individual_input_index: individual_input_index
                                }); // FIXME: Find a better structure than sending indices.
                                // Ignore errors. If the thread is shutting down, it's ok to lose messages.
                            }));
                }
            }
        }
         */

        MonitorTask {
            state: MonitorTaskState {
                trigger_condition_state: trigger_condition_state,
                input_state: full_input_state,
                witnesses: witnesses,
                app: app,
            },
            comm: MonitorComm {
                tx: tx,
                rx: rx,
            }
        }
    }

    fn run(&mut self) {
        for msg in &self.comm.rx {
            use self::MonitorOp::*;
            match msg {
                Update {
                    data,
                    index,
                } => {
                    // Update the state
                    self.state.set_state(&index, Some(data));

                    // Find out if we should execute triggers.
                    // FIXME: We could optimize this by finding out which triggers
                    // are tainted by the update and only rechecking these.
                    for (trigger, trigger_condition_state) in Zip::new((&self.state.app.code, &mut self.state.trigger_condition_state)) {
                        if trigger.condition.is_met(&self.state.input_state) {
                            if !trigger_condition_state.are_conditions_met {
                                // Conditions were not met, now they are, so it is
                                // time to start executing. We copy the inputs
                                // and dispatch to a background thread

                                // FIXME: Handle cooldown.

                                trigger_condition_state.are_conditions_met = true;
                                let _ = self.comm.tx.send(MonitorOp::Execute {
                                    state: self.state.input_state.clone(),
                                    commands: trigger.execute.clone()
                                }); // Ignore errors. If the thread is shutting down, it's ok to lose messages.
                            }
                        } else {
                            trigger_condition_state.are_conditions_met = false;
                        }
                    }
                },
                Execute {..} => {
                    panic!("Not implemented");
                }
                Stop => {
                    // Clean up watcher, stop the thread.
                    self.state.witnesses.clear();
                    return;
                }
            }
        }
    }
}

enum MonitorOp {
    Update{data: Json, index: InputIndex},
    Execute{state: InputState, commands: Vec<Command>},
    Stop
}

impl MonitorApp {
    pub fn start(&mut self) {
        if self.is_running {
            return;
        }
        self.is_running = true;

        let mut task = MonitorTask::new(self.clone());
        thread::spawn(move || {
            task.run();
        });
    }
}

/// Data labelled with a user-readable name.
#[derive(Clone)]
struct Named<T> {
    /// User-readable name.
    name: String,

    data: T,
}

/// A resource needed by this application. Typically, a definition of
/// device with some input our output capabilities.
#[derive(Clone)]
struct Requirement {
    /// The kind of resource, e.g. "a flashbulb".
    kind: DeviceKind,

    /// Input capabilities we need from the device, e.g. "the time of
    /// day", "the current temperature".
    inputs: Vec<Named<InputCapability>>,

    /// Output capabilities we need from the device, e.g. "play a
    /// sound", "set luminosity".
    outputs: Vec<Named<OutputCapability>>,

    /// Minimal number of resources required. If unspecified in the
    /// script, this is 1.
    min: u32,

    /// Maximal number of resources that may be handled. If
    /// unspecified in the script, this is the same as `min`.
    max: u32,

    // FIXME: We may need cooldown properties.
}

/// A single trigger, i.e. "when some condition becomes true, do
/// something".
#[derive(Clone)]
struct Trigger {
    /// The condition in which to execute the trigger.
    condition: Disjunction,

    /// Stuff to do once `condition` is met.
    execute: Vec<Command>,

    /// Minimal duration between two executions of the trigger.  If a
    /// duration was not picked by the developer, a reasonable default
    /// duration should be picked (e.g. 10 minutes).
    cooldown: Duration,
}

/// A disjunction (e.g. a "or") of conditions.
///
/// # Example
///
/// Door alarm #1 OR door alarm #2
#[derive(Clone)]
struct Disjunction {
    /// The disjunction is true iff any of the following conjunctions is true.
    any: Vec<Conjunction>
}

impl Disjunction {
    fn is_met(&self, input_state: &InputState) -> bool {
        panic!("Not implemented");
    }
}

/// A conjunction (e.g. a "and") of conditions.
#[derive(Clone)]
struct Conjunction {
    /// The conjunction is true iff all of the following expressions evaluate to true.
    all: Vec<Expression>
}

#[derive(Clone)]
enum Value {
    Json(Json),
    Blob{data: Arc<Vec<u8>>, mime_type: String},
}

/// An expression in the language.  Note that expressions may contain
/// inputs, which are typically asynchronous. Consequently,
/// expressions are evaluated asynchronously.
#[derive(Clone)]
enum Expression {
    Const {
        value: Value,

        /// We are dealing with real-world values, so physical units
        /// will prevent real-world accidents.
        unit: (), // FIXME: An actual unit

        /// The source for this value.  Used whenever we need to find
        /// out which sensor triggered the trigger (e.g. "where is the
        /// fire?").
        sources: Vec<usize>,
    },

    /// Dynamic values, including both actual sensors and higher-level values.
    ///
    /// # Example
    ///
    /// "Is there movement on motion detector" (may be true/false)
    ///
    /// # Example
    ///
    /// "Date of the latest motion on motion detector" (a Date)
    Input {
        /// A reference to the device used for input.
        /// This is an index in `requirements` and `allocations`.
        index: usize, // FIXME: We should use a custom type.

        /// A property to fetch (e.g. "luminosity" or "meta/latest-on").
        property: InputCapability,
    },

    /// Pure functions on values. The fact that they are pure
    /// functions is important, as it lets us find out automatically
    /// which subexpressions (including inputs) do not need to be
    /// re-evaluated.
    Function {
        function: Function,
        // FIXME: use a Box<> for now to avoid recursive type.
        arguments: Vec<Box<Expression>>
    },
}

#[derive(Clone)]
enum Function {
    // Operations on all values.
    InRange,
    OutOfRange,
    // Operations on strings
    Contains,
    NotContains,
}

/*
enum Function {
    // Operations on all values.
    Equals,
    NotEquals,

    // Operations on numbers, dates, durations.
    GreaterEq,
    Greater,
    LowerEq,
    Lower,
    Plus,
    Minus,

    // Operations on strings
    Contains,
    NotContains,

    // Etc.  FIXME: We'll need operations on dates, extracting name
    // from device, etc.
}
 */

/// Stuff to actually do. In practice, this is always a REST call.
// FIXME: Need to decide how much we wish to sandbox apps.
#[derive(Clone)]
struct Command {
    /// The resource to which this command applies,
    /// as an index in Trigger.requirements/allocations.
    destination: usize,  // FIXME: Use custom type.

    action: OutputCapability,

    arguments: HashMap<String, Option<Expression>>
}

<commit_msg>[fxbox/thinkerbell] Minor cleanups<commit_after>
#![allow(unused_variables)]
#![allow(dead_code)]

/// Basic structure of a Monitor (aka Server App, aka wtttttt)
///
/// Monitors are designed so that the FoxBox can offer a simple
/// IFTTT-style Web UX to let users write their own scripts. More
/// complex monitors can installed from the web from a master device
/// (i.e. the user's cellphone or smart tv).

use dependencies::{DeviceKind, InputCapability, OutputCapability, Device, Range, Watcher, Witness};

use std::time::Duration;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;

extern crate rustc_serialize;
use self::rustc_serialize::json::Json;

extern crate itertools;
use self::itertools::Zip;

/// A Monitor Application, i.e. an application (or a component of an
/// application) executed on the server.
///
/// Monitor applications are typically used for triggering an action
/// in reaction to an event: changing temperature when night falls,
/// ringing an alarm when a door is opened, etc.
///
/// Monitor applications are installed from a paired device. They may
/// either be part of a broader application (which can install them
/// through a web/REST API) or live on their own.
#[derive(Clone)]
struct MonitorApp {
    metadata: (), // FIXME: Authorizations, author, description, update url, version, ...

    /// `true` if the app is on, `false` otherwise.
    is_active: bool,

    /// Monitor applications have sets of requirements (e.g. "I need a
    /// camera"), which are allocated to actual resources through the
    /// UX. Re-allocating resources may be requested by the user, the
    /// foxbox, or an application, e.g. when replacing a device or
    /// upgrading the app.
    ///
    /// The position in the vector is important, as it is used to
    /// represent the instances of resources in the script.
    ///
    /// FIXME: Turn this `Vec` (and others) into a data structure in
    /// which this indexing property is built-in.
    requirements: Vec<Named<Requirement>>,

    /// For each requirement, the resources actually allocated to
    /// match the requirements. This may be 1 or more individual
    /// devices.
    ///
    /// Allocations can be done in several ways:
    ///
    /// - when entering the script through a UX (either the script or
    ///   the UX can suggest allocations);
    /// - when installing an application with a web front-end.
    allocations: Vec<Vec<Named<Arc<Device>>>>,

    code: Vec<Trigger>,

    is_running: bool,
}

impl<'a> MonitorApp {
/*
    Ideally, I'd like something along these lines.
    But, as rustc kindly pointed out to me, that's pretty much unsafe.

    fn iter_state_index(&'a self) -> Box<Iterator<Item=InputIndex> + 'a>
    {
        Box::new(
            Zip::new((&self.requirements, &self.allocations, 0..)).
                flat_map(|(req, allocation, allocation_index)| {
                    let allocation_index_clone = allocation_index.clone();
                    Zip::new((allocation, 0..)).
                        flat_map(|(individual_device, individual_device_index)| {
                            Zip::new((&req.data.inputs, 0..)).
                                map(|(_, individual_input_index)| {
                                    InputIndex {
                                        allocation: allocation_index_clone,
                                        device: individual_device_index,
                                        input: individual_input_index
                                    }
                                })
                        })
                }))
}
     */
    fn iter_state_index(&'a self) -> Vec<InputIndex>
    {
        let mut vec = Vec::new();
        for (req, allocation, allocation_index) in Zip::new((&self.requirements, &self.allocations, 0..)) {
            for (individual_device, individual_device_index) in Zip::new((allocation, 0..)) {
                for (input, individual_input_index) in Zip::new((&req.data.inputs, 0..)) {
                    vec.push(InputIndex {
                        allocation: allocation_index,
                        device: individual_device_index,
                        input: individual_input_index
                    })
                }
            }
        }
        vec
    }

    fn get_individual_device(&self, index: &InputIndex) -> Arc<Device> {
        self.allocations[index.allocation][index.device].data.clone()
    }

    fn get_input(&self, index: &InputIndex) -> InputCapability {
        self.requirements[index.allocation].data.inputs[index.input].data.clone()
    }
}

struct InputIndex {
    allocation: usize,
    device: usize,
    input: usize,
}

struct ConditionState {
    are_conditions_met: bool
}

type InputState = Vec<Vec<Vec<Option<Json>>>>;
struct MonitorTaskState {
    // Invariant: len() is the same as that of app.code
    trigger_condition_state: Vec<ConditionState>,

    /// For each device set allocated, for each individual device
    /// allocated, for each input watched by the app, the latest state
    /// received.
    // Invariant: outer len() is the same as that of self.requirements.
    // Invariant: inner len() is the same as number of input devices bound
    // to the corresponding requirement. May be empty.
    input_state: InputState,

    witnesses: Vec<Witness>,

    app: MonitorApp,
}
impl MonitorTaskState {
    fn set_state(&mut self, index: &InputIndex, value: Option<Json>) {
        self.input_state[index.allocation][index.device][index.input] = value;
    }
}

struct MonitorComm {
    tx: Sender<MonitorOp>,
    rx: Receiver<MonitorOp>,
}
struct MonitorTask {
    state: MonitorTaskState,
    comm: MonitorComm,
}

impl MonitorTask {
    fn new(app: MonitorApp) -> Self {
        // Initialize condition state.
        let mut trigger_condition_state = Vec::with_capacity(app.code.len());
        for _ in &app.code {
            trigger_condition_state.push(ConditionState {
                are_conditions_met: false,
            });
        }
        assert_eq!(trigger_condition_state.len(), app.code.len());

        // Initialize input state.
        let mut full_input_state = Vec::with_capacity(app.requirements.len());
        for (req, allocation) in app.requirements.iter().zip(&app.allocations) {

            // State for this allocation. A single allocation may map
            // to a number of inputs (e.g. "all fire alarms").
            let mut allocation_state = Vec::with_capacity(allocation.len());
            for individual_device in allocation {
                let mut individual_device_state = Vec::with_capacity(req.data.inputs.len());
                for _ in 0 .. req.data.inputs.len() {
                    individual_device_state.push(None);
                }
                allocation_state.push(individual_device_state);
            }
            assert_eq!(allocation_state.len(), allocation.len());
            full_input_state.push(allocation_state);
        }
        assert_eq!(full_input_state.len(), app.requirements.len());

        // Start watching
        let mut watcher = Watcher::new();
        let mut witnesses = Vec::new();
        let (tx, rx) = channel();

        for state_index in app.iter_state_index() {
            // FIXME: We currently use `Range::any()` for simplicity.
            // However, in most cases, we should be able to look inside
            // the condition to build a better `Range`.
            witnesses.push(
                watcher.add(
                    &app.get_individual_device(&state_index), // FIXME: Implement
                    &app.get_input(&state_index), // FIXME: Implement
                    &Range::any(),
                    |data| {
                        let _ = tx.send(MonitorOp::Update {
                            data: data,
                            index: state_index,
                        });
                        // Ignore errors. If the thread is shutting down, it's ok to lose messages.
                    }));
        }

        MonitorTask {
            state: MonitorTaskState {
                trigger_condition_state: trigger_condition_state,
                input_state: full_input_state,
                witnesses: witnesses,
                app: app,
            },
            comm: MonitorComm {
                tx: tx,
                rx: rx,
            }
        }
    }

    fn run(&mut self) {
        for msg in &self.comm.rx {
            use self::MonitorOp::*;
            match msg {
                Update {
                    data,
                    index,
                } => {
                    // Update the state
                    self.state.set_state(&index, Some(data));

                    // Find out if we should execute triggers.
                    // FIXME: We could optimize this by finding out which triggers
                    // are tainted by the update and only rechecking these.
                    for (trigger, trigger_condition_state) in Zip::new((&self.state.app.code, &mut self.state.trigger_condition_state)) {
                        let is_met = trigger.condition.is_met(&self.state.input_state);
                        if is_met == trigger_condition_state.are_conditions_met {
                            // No change in conditions. Nothing to do.
                            continue;
                        }
                        trigger_condition_state.are_conditions_met = is_met;
                        if !is_met {
                            // Conditions were met, now they are not anymore.
                            // The next time they are met, we can trigger
                            // a new execution.
                            continue;
                        }
                        // Conditions were not met, now they are, so it is
                        // time to start executing. We copy the inputs
                        // and dispatch to a background thread

                        // FIXME: Handle cooldown.

                        trigger_condition_state.are_conditions_met = true;
                        let _ = self.comm.tx.send(MonitorOp::Execute {
                            state: self.state.input_state.clone(),
                            commands: trigger.execute.clone()
                        });
                        // Ignore errors. If the thread is shutting down, it's ok to lose messages.
                    }
                },
                Execute {..} => {
                    panic!("Not implemented");
                }
                Stop => {
                    // Clean up watcher, stop the thread.
                    self.state.witnesses.clear();
                    return;
                }
            }
        }
    }
}

enum MonitorOp {
    Update{data: Json, index: InputIndex},
    Execute{state: InputState, commands: Vec<Command>},
    Stop
}

impl MonitorApp {
    pub fn start(&mut self) {
        if self.is_running {
            return;
        }
        self.is_running = true;

        let mut task = MonitorTask::new(self.clone());
        thread::spawn(move || {
            task.run();
        });
    }
}

/// Data labelled with a user-readable name.
#[derive(Clone)]
struct Named<T> {
    /// User-readable name.
    name: String,

    data: T,
}

/// A resource needed by this application. Typically, a definition of
/// device with some input our output capabilities.
#[derive(Clone)]
struct Requirement {
    /// The kind of resource, e.g. "a flashbulb".
    kind: DeviceKind,

    /// Input capabilities we need from the device, e.g. "the time of
    /// day", "the current temperature".
    inputs: Vec<Named<InputCapability>>,

    /// Output capabilities we need from the device, e.g. "play a
    /// sound", "set luminosity".
    outputs: Vec<Named<OutputCapability>>,

    /// Minimal number of resources required. If unspecified in the
    /// script, this is 1.
    min: u32,

    /// Maximal number of resources that may be handled. If
    /// unspecified in the script, this is the same as `min`.
    max: u32,

    // FIXME: We may need cooldown properties.
}

/// A single trigger, i.e. "when some condition becomes true, do
/// something".
#[derive(Clone)]
struct Trigger {
    /// The condition in which to execute the trigger.
    condition: Disjunction,

    /// Stuff to do once `condition` is met.
    execute: Vec<Command>,

    /// Minimal duration between two executions of the trigger.  If a
    /// duration was not picked by the developer, a reasonable default
    /// duration should be picked (e.g. 10 minutes).
    cooldown: Duration,
}

/// A disjunction (e.g. a "or") of conditions.
///
/// # Example
///
/// Door alarm #1 OR door alarm #2
#[derive(Clone)]
struct Disjunction {
    /// The disjunction is true iff any of the following conjunctions is true.
    any: Vec<Conjunction>
}

impl Disjunction {
    fn is_met(&self, input_state: &InputState) -> bool {
        panic!("Not implemented");
    }
}

/// A conjunction (e.g. a "and") of conditions.
#[derive(Clone)]
struct Conjunction {
    /// The conjunction is true iff all of the following expressions evaluate to true.
    all: Vec<Expression>
}

#[derive(Clone)]
enum Value {
    Json(Json),
    Blob{data: Arc<Vec<u8>>, mime_type: String},
}

/// An expression in the language.  Note that expressions may contain
/// inputs, which are typically asynchronous. Consequently,
/// expressions are evaluated asynchronously.
#[derive(Clone)]
enum Expression {
    Const {
        value: Value,

        /// We are dealing with real-world values, so physical units
        /// will prevent real-world accidents.
        unit: (), // FIXME: An actual unit

        /// The source for this value.  Used whenever we need to find
        /// out which sensor triggered the trigger (e.g. "where is the
        /// fire?").
        sources: Vec<usize>,
    },

    /// Dynamic values, including both actual sensors and higher-level values.
    ///
    /// # Example
    ///
    /// "Is there movement on motion detector" (may be true/false)
    ///
    /// # Example
    ///
    /// "Date of the latest motion on motion detector" (a Date)
    Input {
        /// A reference to the device used for input.
        /// This is an index in `requirements` and `allocations`.
        index: usize, // FIXME: We should use a custom type.

        /// A property to fetch (e.g. "luminosity" or "meta/latest-on").
        property: InputCapability,
    },

    /// Pure functions on values. The fact that they are pure
    /// functions is important, as it lets us find out automatically
    /// which subexpressions (including inputs) do not need to be
    /// re-evaluated.
    Function {
        function: Function,
        // FIXME: use a Box<> for now to avoid recursive type.
        arguments: Vec<Box<Expression>>
    },
}

#[derive(Clone)]
enum Function {
    // Operations on all values.
    InRange,
    OutOfRange,
    // Operations on strings
    Contains,
    NotContains,
}

/*
enum Function {
    // Operations on all values.
    Equals,
    NotEquals,

    // Operations on numbers, dates, durations.
    GreaterEq,
    Greater,
    LowerEq,
    Lower,
    Plus,
    Minus,

    // Operations on strings
    Contains,
    NotContains,

    // Etc.  FIXME: We'll need operations on dates, extracting name
    // from device, etc.
}
 */

/// Stuff to actually do. In practice, this is always a REST call.
// FIXME: Need to decide how much we wish to sandbox apps.
#[derive(Clone)]
struct Command {
    /// The resource to which this command applies,
    /// as an index in Trigger.requirements/allocations.
    destination: usize,  // FIXME: Use custom type.

    action: OutputCapability,

    arguments: HashMap<String, Option<Expression>>
}

<|endoftext|>


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

use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};

pub fn target() -> Result<Target, String> {
    let mut post_link_args = LinkArgs::new();
    post_link_args.insert(LinkerFlavor::Em,
                          vec!["-s".to_string(),
                               "BINARYEN=1".to_string(),
                               "-s".to_string(),
                               "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);

    let opts = TargetOptions {
        dynamic_linking: false,
        executables: true,
        // Today emcc emits two files - a .js file to bootstrap and
        // possibly interpret the wasm, and a .wasm file
        exe_suffix: ".js".to_string(),
        linker_is_gnu: true,
        allow_asm: false,
        obj_is_bitcode: true,
        is_like_emscripten: true,
        max_atomic_width: Some(32),
        post_link_args,
        target_family: Some("unix".to_string()),
        codegen_backend: "emscripten".to_string(),
        .. Default::default()
    };
    Ok(Target {
        llvm_target: "asmjs-unknown-emscripten".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "emscripten".to_string(),
        target_env: String::new(),
        target_vendor: "unknown".to_string(),
        data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
        arch: "wasm32".to_string(),
        linker_flavor: LinkerFlavor::Em,
        options: opts,
    })
}
<commit_msg>Set BINARYEN_TRAP_MODE=clamp<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};

pub fn target() -> Result<Target, String> {
    // FIXME(nikic) BINARYEN_TRAP_MODE=clamp is needed to avoid trapping in our
    // -Zsaturating-float-casts implementation. This can be dropped if/when
    // we have native fpto[su]i.sat intrinsics, or the implementation otherwise
    // stops relying on non-trapping fpto[su]i.
    let mut post_link_args = LinkArgs::new();
    post_link_args.insert(LinkerFlavor::Em,
                          vec!["-s".to_string(),
                               "BINARYEN=1".to_string(),
                               "-s".to_string(),
                               "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
                               "-s".to_string(),
                               "BINARYEN_TRAP_MODE='clamp'".to_string()]);

    let opts = TargetOptions {
        dynamic_linking: false,
        executables: true,
        // Today emcc emits two files - a .js file to bootstrap and
        // possibly interpret the wasm, and a .wasm file
        exe_suffix: ".js".to_string(),
        linker_is_gnu: true,
        allow_asm: false,
        obj_is_bitcode: true,
        is_like_emscripten: true,
        max_atomic_width: Some(32),
        post_link_args,
        target_family: Some("unix".to_string()),
        codegen_backend: "emscripten".to_string(),
        .. Default::default()
    };
    Ok(Target {
        llvm_target: "asmjs-unknown-emscripten".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "emscripten".to_string(),
        target_env: String::new(),
        target_vendor: "unknown".to_string(),
        data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
        arch: "wasm32".to_string(),
        linker_flavor: LinkerFlavor::Em,
        options: opts,
    })
}
<|endoftext|>