<commit_before>//! Licensed under the Apache License, Version 2.0
//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
//! http://opensource.org/licenses/MIT, at your
//! option. This file may not be copied, modified, or distributed
//! except according to those terms.

use std::kinds;
use std::mem;
use std::ptr;
use std::fmt;

use std::num::Saturating;

/// Similar to the slice iterator, but with a certain number of steps
/// (stride) skipped per iteration.
///
/// Does not support zero-sized `T`.
///
/// Iterator element type is `&'a A`
pub struct Stride<'a, A> {
    begin: *const A,
    // Unlike the slice iterator, end is inclusive and the last
    // pointer we will visit. This makes it possible to have
    // safe stride iterators for columns in matrices etc.
    end: *const A,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
}

impl<'a, A> Stride<'a, A>
{
    /// Create Stride iterator from a slice and the element step count
    ///
    /// ## Example
    ///
    /// ```
    /// let xs = [0i, 1, 2, 3, 4, 5];
    /// let mut iter = Stride::from_slice(xs.as_slice(), 2);
    /// ```
    pub fn from_slice(xs: &'a [A], step: uint) -> Stride<'a, A>
    {
        assert!(step != 0);
        let mut begin = ptr::null();
        let mut end = ptr::null();
        let nelem = xs.len().saturating_add(step - 1) / step;
        unsafe {
            if nelem != 0 {
                begin = xs.as_ptr();
                end = begin.offset(((nelem - 1) * step) as int);
            }
            Stride::from_ptrs(begin, end, step as int)
        }
    }

    /// Create Stride iterator from raw pointers from the *inclusive*
    /// pointer range [begin, end].
    ///
    /// **Note:** `end` **must** be a whole number of `stride` steps away
    /// from `begin`
    pub unsafe fn from_ptrs(begin: *const A, end: *const A, stride: int) -> Stride<'a, A>
    {
        Stride {
            begin: begin,
            end: end,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
        }
    }

    /// Swap the being and end pointer and reverse the stride,
    /// in effect reversing the iterator.
    #[inline]
    pub fn swap_ends(&mut self) {
        if !self.begin.is_null() {
            mem::swap(&mut self.begin, &mut self.end);
            self.stride = -self.stride;
        }
    }
}

impl<'a, A> Iterator<&'a A> for Stride<'a, A>
{
    #[inline]
    fn next(&mut self) -> Option<&'a A>
    {
        if self.begin.is_null() {
            None
        } else {
            unsafe {
                let elt: &'a A = mem::transmute(self.begin);
                if self.begin == self.end {
                    self.begin = ptr::null();
                } else {
                    self.begin = self.begin.offset(self.stride);
                }
                Some(elt)
            }
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>)
    {
        let len;
        if self.begin.is_null() {
            len = 0;
        } else {
            len = (self.end as uint - self.begin as uint) as int / self.stride
                / mem::size_of::<A>() as int + 1;
        }

        (len as uint, Some(len as uint))
    }
}

impl<'a, A> DoubleEndedIterator<&'a A> for Stride<'a, A>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a A>
    {
        if self.begin.is_null() {
            None
        } else {
            unsafe {
                let elt: &'a A = mem::transmute(self.end);
                if self.begin == self.end {
                    self.begin = ptr::null();
                } else {
                    self.end = self.end.offset(-self.stride);
                }
                Some(elt)
            }
        }
    }
}

impl<'a, A> ExactSize<&'a A> for Stride<'a, A> { }

impl<'a, A> Index<uint, A> for Stride<'a, A>
{
    fn index<'b>(&'b self, i: &uint) -> &'b A
    {
        assert!(*i < self.size_hint().val0());
        unsafe {
            let ptr = self.begin.offset(self.stride * (*i as int));
            mem::transmute(ptr)
        }
    }
}

impl<'a, A: fmt::Show> fmt::Show for Stride<'a, A>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        let it = *self;
        try!(write!(f, "["));
        for (i, elt) in it.enumerate() {
            if i != 0 {
                try!(write!(f, ", "));
            }
            try!(write!(f, "{}", *elt));
        }
        write!(f, "]")
    }
}

impl<'a, A> Clone for Stride<'a, A>
{
    fn clone(&self) -> Stride<'a, A>
    {
        *self
    }
}
<commit_msg>Stride: Fixes about zero-size A (not supported)<commit_after>//! Licensed under the Apache License, Version 2.0
//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
//! http://opensource.org/licenses/MIT, at your
//! option. This file may not be copied, modified, or distributed
//! except according to those terms.

use std::kinds;
use std::mem;
use std::ptr;
use std::fmt;

use std::num::Saturating;

/// Similar to the slice iterator, but with a certain number of steps
/// (stride) skipped per iteration.
///
/// Does not support zero-sized `A`.
///
/// Iterator element type is `&'a A`
pub struct Stride<'a, A> {
    begin: *const A,
    // Unlike the slice iterator, end is inclusive and the last
    // pointer we will visit. This makes it possible to have
    // safe stride iterators for columns in matrices etc.
    end: *const A,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
}

impl<'a, A> Stride<'a, A>
{
    /// Create Stride iterator from a slice and the element step count
    ///
    /// ## Example
    ///
    /// ```
    /// let xs = [0i, 1, 2, 3, 4, 5];
    /// let mut iter = Stride::from_slice(xs.as_slice(), 2);
    /// ```
    pub fn from_slice(xs: &'a [A], step: uint) -> Stride<'a, A>
    {
        assert!(step != 0);
        assert!(mem::size_of::<A>() != 0);
        let mut begin = ptr::null();
        let mut end = ptr::null();
        let nelem = xs.len().saturating_add(step - 1) / step;
        unsafe {
            if nelem != 0 {
                begin = xs.as_ptr();
                end = begin.offset(((nelem - 1) * step) as int);
            }
            Stride::from_ptrs(begin, end, step as int)
        }
    }

    /// Create Stride iterator from raw pointers from the *inclusive*
    /// pointer range [begin, end].
    ///
    /// **Note:** `end` **must** be a whole number of `stride` steps away
    /// from `begin`
    pub unsafe fn from_ptrs(begin: *const A, end: *const A, stride: int) -> Stride<'a, A>
    {
        Stride {
            begin: begin,
            end: end,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
        }
    }

    /// Swap the being and end pointer and reverse the stride,
    /// in effect reversing the iterator.
    #[inline]
    pub fn swap_ends(&mut self) {
        if !self.begin.is_null() {
            mem::swap(&mut self.begin, &mut self.end);
            self.stride = -self.stride;
        }
    }
}

impl<'a, A> Iterator<&'a A> for Stride<'a, A>
{
    #[inline]
    fn next(&mut self) -> Option<&'a A>
    {
        if self.begin.is_null() {
            None
        } else {
            unsafe {
                let elt: &'a A = mem::transmute(self.begin);
                if self.begin == self.end {
                    self.begin = ptr::null();
                } else {
                    self.begin = self.begin.offset(self.stride);
                }
                Some(elt)
            }
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>)
    {
        let len;
        if self.begin.is_null() {
            len = 0;
        } else {
            len = (self.end as uint - self.begin as uint) as int / self.stride
                / mem::size_of::<A>() as int + 1;
        }

        (len as uint, Some(len as uint))
    }
}

impl<'a, A> DoubleEndedIterator<&'a A> for Stride<'a, A>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a A>
    {
        if self.begin.is_null() {
            None
        } else {
            unsafe {
                let elt: &'a A = mem::transmute(self.end);
                if self.begin == self.end {
                    self.begin = ptr::null();
                } else {
                    self.end = self.end.offset(-self.stride);
                }
                Some(elt)
            }
        }
    }
}

impl<'a, A> ExactSize<&'a A> for Stride<'a, A> { }

impl<'a, A> Index<uint, A> for Stride<'a, A>
{
    fn index<'b>(&'b self, i: &uint) -> &'b A
    {
        assert!(*i < self.size_hint().val0());
        unsafe {
            let ptr = self.begin.offset(self.stride * (*i as int));
            mem::transmute(ptr)
        }
    }
}

impl<'a, A: fmt::Show> fmt::Show for Stride<'a, A>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        let it = *self;
        try!(write!(f, "["));
        for (i, elt) in it.enumerate() {
            if i != 0 {
                try!(write!(f, ", "));
            }
            try!(write!(f, "{}", *elt));
        }
        write!(f, "]")
    }
}

impl<'a, A> Clone for Stride<'a, A>
{
    fn clone(&self) -> Stride<'a, A>
    {
        *self
    }
}
<|endoftext|>


<commit_before>use parse_args;
use std::io::{BufRead, BufReader};
use std::fs::File;
use std::collections::HashSet;

use filter::sv_locus_identifiers as sv_locus_identifiers;

const USAGE: &'static str = "
Usage:
  breakfast blacklist [options] <sv_files>...

Options:
  --freq-above=FREQ     Minimum samples to consider [default: 0]
";

pub fn main() {
    let args = parse_args(USAGE);
    let min_frequency: f32 = args.get_str("--freq-above").parse().unwrap();
	let sv_files = args.get_vec("<sv_files>").to_vec();

    println!("Total samples  {}", sv_files.len());
    let mut sample_variants: Vec<HashSet<String>> = Vec::with_capacity(sv_files.len());

    println!("Before {}", sample_variants.len());

    for (s, sv_file) in sv_files.iter().enumerate() {
        let sv = BufReader::new(File::open(&sv_file).unwrap());

        for l in sv.lines() {
            let line = l.unwrap();
            if !line.starts_with("chr") { continue; }

            let tokens: Vec<&str> = line.split('\t').collect();
            let chrom = tokens[0];
            let pos: usize = tokens[2].parse().unwrap();
            let tmp1: HashSet<_> = sv_locus_identifiers(chrom, pos, 5000).into_iter().collect();

            let chrom = tokens[5];
            let pos: usize = tokens[7].parse().unwrap();
            let tmp2: HashSet<_> = sv_locus_identifiers(chrom, pos, 5000).into_iter().collect();

            let tmp: HashSet<String> = tmp1.union(&tmp2).cloned().collect();
            sample_variants.push(tmp);
        }
    }

     let variants_cp = sample_variants.to_vec();
     let mut blacklist: HashSet<String> = HashSet::new();
     for loci in sample_variants {
        for l in loci {
         blacklist.insert(l);
        }
     }
     blacklist = natural_sorted(blacklist);

    let mut frequency: Vec<usize> = vec![0; blacklist.len()];
    for (k, bad_variant) in blacklist.iter().enumerate() {
        let bad_in_sample: Vec<usize> = Vec::new();
    }

    //println!("{:?}", frequency);
    //println!("{:?}", &blacklist.len());

}

pub fn natural_sorted(blacklist: HashSet<String>) -> HashSet<String> {
    let mut v: Vec<String> = blacklist.into_iter().collect();
    v.sort_by(|a, b| a.cmp(b));
    let out: HashSet<_> = v.into_iter().collect();
    out
}
<commit_msg>	modified:   src/blacklist.rs<commit_after>use parse_args;
use std::io::{BufRead, BufReader};
use std::fs::File;
use std::collections::HashSet;

use filter::sv_locus_identifiers as sv_locus_identifiers;

const USAGE: &'static str = "
Usage:
  breakfast blacklist [options] <sv_files>...

Options:
  --freq-above=FREQ     Minimum samples to consider [default: 0]
";

pub fn main() {
    let args = parse_args(USAGE);
    let min_frequency: f32 = args.get_str("--freq-above").parse().unwrap();
	let sv_files = args.get_vec("<sv_files>").to_vec();

    println!("Total samples  {}", sv_files.len());
    let mut sample_variants: Vec<HashSet<String>> = Vec::with_capacity(sv_files.len());

    println!("Before {}", sample_variants.len());

    for (s, sv_file) in sv_files.iter().enumerate() {
        let sv = BufReader::new(File::open(&sv_file).unwrap());

        for l in sv.lines() {
            let line = l.unwrap();
            if !line.starts_with("chr") { continue; }

            let tokens: Vec<&str> = line.split('\t').collect();
            let chrom = tokens[0];
            let pos: usize = tokens[2].parse().unwrap();
            let tmp1: HashSet<_> = sv_locus_identifiers(chrom, pos, 5000).into_iter().collect();

            let chrom = tokens[5];
            let pos: usize = tokens[7].parse().unwrap();
            let tmp2: HashSet<_> = sv_locus_identifiers(chrom, pos, 5000).into_iter().collect();

            let tmp: HashSet<String> = tmp1.union(&tmp2).cloned().collect();
            sample_variants.push(tmp);
        }
    }

     let variants_cp = sample_variants.to_vec();
     let mut blacklist: HashSet<String> = HashSet::new();
     for loci in variants_cp {
        for l in loci {
         blacklist.insert(l);
        }
     }
     blacklist = natural_sorted(blacklist);

    let mut frequency: Vec<f32> = vec![0.0; blacklist.len()];
    for (k, bad_variant) in blacklist.iter().enumerate() {
        let mut bad_in_sample: Vec<usize> = vec![0; sample_variants.len()];
        for (n, loci) in sample_variants.iter().enumerate() {
            if loci.contains(bad_variant) {
                bad_in_sample[n] = 1;
                }
            }
        let sum: usize = bad_in_sample.iter().sum();
        frequency[k]   = (sum / bad_in_sample.len()) as f32;
        println!("{}\t{}\t{}\t{}", sum, bad_in_sample.len(), frequency[k], min_frequency);
    }

    //println!("{:?}", frequency);
    //println!("{:?}", &blacklist.len());
}

pub fn natural_sorted(blacklist: HashSet<String>) -> HashSet<String> {
    let mut v: Vec<String> = blacklist.into_iter().collect();
    v.sort_by(|a, b| a.cmp(b));
    let out: HashSet<_> = v.into_iter().collect();
    out
}
<|endoftext|>


<commit_before>//! A byte-offset based string table.
//! Commonly used in ELF binaries, Unix archives, and even PE binaries.

use core::ops::Index;
use core::slice;
use core::str;
use core::fmt;
use scroll::{self, ctx, Pread};
#[cfg(feature = "std")]
use error;

/// A common string table format which is indexed by byte offsets (and not
/// member index). Constructed using [`parse`](#method.parse)
/// with your choice of delimiter. Please be careful.
pub struct Strtab<'a> {
    bytes: &'a[u8],
    delim: ctx::StrCtx,
}

#[inline(always)]
fn get_str(offset: usize, bytes: &[u8], delim: ctx::StrCtx) -> scroll::Result<&str> {
    bytes.pread_with::<&str>(offset, delim)
}

impl<'a> Strtab<'a> {
    /// Construct a new strtab with `bytes` as the backing string table, using `delim` as the delimiter between entries
    pub fn new (bytes: &'a [u8], delim: u8) -> Self {
        Strtab { delim: ctx::StrCtx::Delimiter(delim), bytes: bytes }
    }
    /// Construct a strtab from a `ptr`, and a `size`, using `delim` as the delimiter
    pub unsafe fn from_raw(ptr: *const u8, size: usize, delim: u8) -> Strtab<'a> {
        Strtab { delim: ctx::StrCtx::Delimiter(delim), bytes: slice::from_raw_parts(ptr, size) }
    }
    #[cfg(feature = "std")]
    /// Parses a strtab from `bytes` at `offset` with `len` size as the backing string table, using `delim` as the delimiter
    pub fn parse(bytes: &'a [u8], offset: usize, len: usize, delim: u8) -> error::Result<Strtab<'a>> {
        if offset + len >= bytes.len () {
            return Err(error::Error::Malformed(format!("Strtable size ({}) + offset ({}) is out of bounds", len, offset)));
        }
        Ok(Strtab { bytes: &bytes[offset..offset+len], delim: ctx::StrCtx::Delimiter(delim) })
    }
    #[cfg(feature = "std")]
    /// Converts the string table to a vector, with the original `delim` used to separate the strings
    pub fn to_vec(self) -> error::Result<Vec<String>> {
        let len = self.bytes.len();
        let mut strings = Vec::with_capacity(len);
        let mut i = 0;
        while i < len {
            let string = self.get(i).unwrap()?;
            i = i + string.len() + 1;
            strings.push(string.to_string());
        }
        Ok(strings)
    }
    /// Safely parses and gets a str reference from the backing bytes starting at byte `offset`.
    /// If the index is out of bounds, `None` is returned
    pub fn get(&self, offset: usize) -> Option<error::Result<&'a str>> {
        if offset >= self.bytes.len() {
            None
        } else {
            Some(get_str(offset, self.bytes, self.delim).map_err(|e| e.into()))
        }
    }
}

impl<'a> fmt::Debug for Strtab<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "delim: {:?} {:?}", self.delim, str::from_utf8(&self.bytes))
    }
}

impl<'a> Default for Strtab<'a> {
    fn default() -> Strtab<'a> {
        Strtab { bytes: &[], delim: ctx::StrCtx::default() }
    }
}

impl<'a> Index<usize> for Strtab<'a> {
    type Output = str;
    /// Gets str reference at starting at byte `offset`.
    /// **NB**: this will panic if the underlying bytes are not valid utf8, or the offset is invalid
    #[inline(always)]
    fn index(&self, offset: usize) -> &Self::Output {
        get_str(offset, &self.bytes, self.delim).unwrap()
    }
}

#[test]
fn as_vec_no_final_null() {
    let bytes = b"\0printf\0memmove\0busta";
    let strtab = unsafe { Strtab::from_raw(bytes.as_ptr(), bytes.len(), 0x0) };
    let vec = strtab.to_vec().unwrap();
    assert_eq!(vec.len(), 4);
    assert_eq!(vec, vec!["", "printf", "memmove", "busta"]);
}

#[test]
fn as_vec_no_first_null_no_final_null() {
    let bytes = b"printf\0memmove\0busta";
    let strtab = unsafe { Strtab::from_raw(bytes.as_ptr(), bytes.len(), 0x0) };
    let vec = strtab.to_vec().unwrap();
    assert_eq!(vec.len(), 3);
    assert_eq!(vec, vec!["printf", "memmove", "busta"]);
}

#[test]
fn to_vec_final_null() {
    let bytes = b"\0printf\0memmove\0busta\0";
    let strtab = unsafe { Strtab::from_raw(bytes.as_ptr(), bytes.len(), 0x0) };
    let vec = strtab.to_vec().unwrap();
    assert_eq!(vec.len(), 4);
    assert_eq!(vec, vec!["", "printf", "memmove", "busta"]);
}

#[test]
fn to_vec_newline_delim() {
    let bytes = b"\nprintf\nmemmove\nbusta\n";
    let strtab = unsafe { Strtab::from_raw(bytes.as_ptr(), bytes.len(), '\n' as u8) };
    let vec = strtab.to_vec().unwrap();
    assert_eq!(vec.len(), 4);
    assert_eq!(vec, vec!["", "printf", "memmove", "busta"]);
}
<commit_msg>Check overflow in strtab (#34)<commit_after>//! A byte-offset based string table.
//! Commonly used in ELF binaries, Unix archives, and even PE binaries.

use core::ops::Index;
use core::slice;
use core::str;
use core::fmt;
use scroll::{self, ctx, Pread};
#[cfg(feature = "std")]
use error;

/// A common string table format which is indexed by byte offsets (and not
/// member index). Constructed using [`parse`](#method.parse)
/// with your choice of delimiter. Please be careful.
pub struct Strtab<'a> {
    bytes: &'a[u8],
    delim: ctx::StrCtx,
}

#[inline(always)]
fn get_str(offset: usize, bytes: &[u8], delim: ctx::StrCtx) -> scroll::Result<&str> {
    bytes.pread_with::<&str>(offset, delim)
}

impl<'a> Strtab<'a> {
    /// Construct a new strtab with `bytes` as the backing string table, using `delim` as the delimiter between entries
    pub fn new (bytes: &'a [u8], delim: u8) -> Self {
        Strtab { delim: ctx::StrCtx::Delimiter(delim), bytes: bytes }
    }
    /// Construct a strtab from a `ptr`, and a `size`, using `delim` as the delimiter
    pub unsafe fn from_raw(ptr: *const u8, size: usize, delim: u8) -> Strtab<'a> {
        Strtab { delim: ctx::StrCtx::Delimiter(delim), bytes: slice::from_raw_parts(ptr, size) }
    }
    #[cfg(feature = "std")]
    /// Parses a strtab from `bytes` at `offset` with `len` size as the backing string table, using `delim` as the delimiter
    pub fn parse(bytes: &'a [u8], offset: usize, len: usize, delim: u8) -> error::Result<Strtab<'a>> {
        let (end, overflow) = offset.overflowing_add(len);
        if overflow || end >= bytes.len () {
            return Err(error::Error::Malformed(format!("Strtable size ({}) + offset ({}) is out of bounds", len, offset)));
        }
        Ok(Strtab { bytes: &bytes[offset..end], delim: ctx::StrCtx::Delimiter(delim) })
    }
    #[cfg(feature = "std")]
    /// Converts the string table to a vector, with the original `delim` used to separate the strings
    pub fn to_vec(self) -> error::Result<Vec<String>> {
        let len = self.bytes.len();
        let mut strings = Vec::with_capacity(len);
        let mut i = 0;
        while i < len {
            let string = self.get(i).unwrap()?;
            i = i + string.len() + 1;
            strings.push(string.to_string());
        }
        Ok(strings)
    }
    /// Safely parses and gets a str reference from the backing bytes starting at byte `offset`.
    /// If the index is out of bounds, `None` is returned
    pub fn get(&self, offset: usize) -> Option<error::Result<&'a str>> {
        if offset >= self.bytes.len() {
            None
        } else {
            Some(get_str(offset, self.bytes, self.delim).map_err(|e| e.into()))
        }
    }
}

impl<'a> fmt::Debug for Strtab<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "delim: {:?} {:?}", self.delim, str::from_utf8(&self.bytes))
    }
}

impl<'a> Default for Strtab<'a> {
    fn default() -> Strtab<'a> {
        Strtab { bytes: &[], delim: ctx::StrCtx::default() }
    }
}

impl<'a> Index<usize> for Strtab<'a> {
    type Output = str;
    /// Gets str reference at starting at byte `offset`.
    /// **NB**: this will panic if the underlying bytes are not valid utf8, or the offset is invalid
    #[inline(always)]
    fn index(&self, offset: usize) -> &Self::Output {
        get_str(offset, &self.bytes, self.delim).unwrap()
    }
}

#[test]
fn as_vec_no_final_null() {
    let bytes = b"\0printf\0memmove\0busta";
    let strtab = unsafe { Strtab::from_raw(bytes.as_ptr(), bytes.len(), 0x0) };
    let vec = strtab.to_vec().unwrap();
    assert_eq!(vec.len(), 4);
    assert_eq!(vec, vec!["", "printf", "memmove", "busta"]);
}

#[test]
fn as_vec_no_first_null_no_final_null() {
    let bytes = b"printf\0memmove\0busta";
    let strtab = unsafe { Strtab::from_raw(bytes.as_ptr(), bytes.len(), 0x0) };
    let vec = strtab.to_vec().unwrap();
    assert_eq!(vec.len(), 3);
    assert_eq!(vec, vec!["printf", "memmove", "busta"]);
}

#[test]
fn to_vec_final_null() {
    let bytes = b"\0printf\0memmove\0busta\0";
    let strtab = unsafe { Strtab::from_raw(bytes.as_ptr(), bytes.len(), 0x0) };
    let vec = strtab.to_vec().unwrap();
    assert_eq!(vec.len(), 4);
    assert_eq!(vec, vec!["", "printf", "memmove", "busta"]);
}

#[test]
fn to_vec_newline_delim() {
    let bytes = b"\nprintf\nmemmove\nbusta\n";
    let strtab = unsafe { Strtab::from_raw(bytes.as_ptr(), bytes.len(), '\n' as u8) };
    let vec = strtab.to_vec().unwrap();
    assert_eq!(vec.len(), 4);
    assert_eq!(vec, vec!["", "printf", "memmove", "busta"]);
}
<|endoftext|>


<commit_before>// Copyright 2013 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

//! Private callback support functions.

use libc::{c_double, c_int, c_uint};
use std::mem;

use super::*;

macro_rules! callback(
    (
        type Args = ($($arg:ident: $arg_ty:ty),*);
        type Callback = $Callback:ident;
        let ext_set = $ext_set:expr;
        fn callback($($ext_arg:ident: $ext_arg_ty:ty),*) $call:expr
    ) => (
        local_data_key!(CALLBACK_KEY: Box<Object<Args> + 'static>)

        type Args = ($($arg_ty),*,);

        trait Object<T> {
            fn call(&self, args: T);
        }

        impl<UserData> Object<Args> for ::Callback<fn($($arg_ty),*, &UserData), UserData> {
            fn call(&self, ($($arg),*,): Args) {
                (self.f)($($arg),*, &self.data);
            }
        }

        pub fn set<UserData: 'static>(f: ::$Callback<UserData>) {
            CALLBACK_KEY.replace(Some(box f as Box<Object<Args> + 'static>));
            ($ext_set)(Some(callback));
        }

        pub fn unset() {
            CALLBACK_KEY.replace(None);
            ($ext_set)(None);
        }

        extern "C" fn callback($($ext_arg: $ext_arg_ty),*) {
            match CALLBACK_KEY.get() {
                Some(cb) => unsafe { cb.call($call) },
                _ => {}
            }
        }
    )
)

pub mod error {
    use libc::{c_int, c_char};
    use std::mem;
    use std::string;

    callback!(
        type Args = (error: ::Error, description: String);
        type Callback = ErrorCallback;
        let ext_set = |cb| unsafe { ::ffi::glfwSetErrorCallback(cb) };
        fn callback(error: c_int, description: *const c_char) {
            (mem::transmute(error), string::String::from_raw_buf(
                mem::transmute(description)))
        }
    )
}

pub mod monitor {
    use libc::{c_int};
    use std::mem;
    use std::kinds::marker;

    callback!(
        type Args = (monitor: ::Monitor, event: ::MonitorEvent);
        type Callback = MonitorCallback;
        let ext_set = |cb| unsafe { ::ffi::glfwSetMonitorCallback(cb) };
        fn callback(monitor: *mut ::ffi::GLFWmonitor, event: c_int) {
            let monitor = ::Monitor {
                ptr: monitor,
                no_copy: marker::NoCopy,
                no_send: marker::NoSend,
                no_share: marker::NoSync,
            };
            (monitor, mem::transmute(event))
        }
    )
}

unsafe fn get_sender<'a>(window: &'a *mut ffi::GLFWwindow) -> &'a Sender<(f64, WindowEvent)> {
    mem::transmute(ffi::glfwGetWindowUserPointer(*window))
}

macro_rules! window_callback(
    (fn $name:ident () => $event:ident) => (
        pub extern "C" fn $name(window: *mut ffi::GLFWwindow) {
            unsafe { get_sender(&window).send((ffi::glfwGetTime() as f64, WindowEvent::$event)); }
        }
     );
    (fn $name:ident ($($ext_arg:ident: $ext_arg_ty:ty),*) => $event:ident($($arg_conv:expr),*)) => (
        pub extern "C" fn $name(window: *mut ffi::GLFWwindow $(, $ext_arg: $ext_arg_ty)*) {
            unsafe { get_sender(&window).send((ffi::glfwGetTime() as f64, WindowEvent::$event($($arg_conv),*))); }
        }
     );
)

window_callback!(fn window_pos_callback(xpos: c_int, ypos: c_int)                           => PosEvent(xpos as i32, ypos as i32))
window_callback!(fn window_size_callback(width: c_int, height: c_int)                       => SizeEvent(width as i32, height as i32))
window_callback!(fn window_close_callback()                                                 => CloseEvent)
window_callback!(fn window_refresh_callback()                                               => RefreshEvent)
window_callback!(fn window_focus_callback(focused: c_int)                                   => FocusEvent(focused == ffi::TRUE))
window_callback!(fn window_iconify_callback(iconified: c_int)                               => IconifyEvent(iconified == ffi::TRUE))
window_callback!(fn framebuffer_size_callback(width: c_int, height: c_int)                  => FramebufferSizeEvent(width as i32, height as i32))
window_callback!(fn mouse_button_callback(button: c_int, action: c_int, mods: c_int)        => MouseButtonEvent(mem::transmute(button), mem::transmute(action), Modifiers::from_bits(mods).unwrap()))
window_callback!(fn cursor_pos_callback(xpos: c_double, ypos: c_double)                     => CursorPosEvent(xpos as f64, ypos as f64))
window_callback!(fn cursor_enter_callback(entered: c_int)                                   => CursorEnterEvent(entered == ffi::TRUE))
window_callback!(fn scroll_callback(xpos: c_double, ypos: c_double)                         => ScrollEvent(xpos as f64, ypos as f64))
window_callback!(fn key_callback(key: c_int, scancode: c_int, action: c_int, mods: c_int)   => KeyEvent(mem::transmute(key), scancode, mem::transmute(action), Modifiers::from_bits(mods).unwrap()))
window_callback!(fn char_callback(character: c_uint)                                        => CharEvent(::std::char::from_u32(character).unwrap()))
<commit_msg>Avoid an unnecessary transmute call.<commit_after>// Copyright 2013 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

//! Private callback support functions.

use libc::{c_double, c_int, c_uint};
use std::mem;

use super::*;

macro_rules! callback(
    (
        type Args = ($($arg:ident: $arg_ty:ty),*);
        type Callback = $Callback:ident;
        let ext_set = $ext_set:expr;
        fn callback($($ext_arg:ident: $ext_arg_ty:ty),*) $call:expr
    ) => (
        local_data_key!(CALLBACK_KEY: Box<Object<Args> + 'static>)

        type Args = ($($arg_ty),*,);

        trait Object<T> {
            fn call(&self, args: T);
        }

        impl<UserData> Object<Args> for ::Callback<fn($($arg_ty),*, &UserData), UserData> {
            fn call(&self, ($($arg),*,): Args) {
                (self.f)($($arg),*, &self.data);
            }
        }

        pub fn set<UserData: 'static>(f: ::$Callback<UserData>) {
            CALLBACK_KEY.replace(Some(box f as Box<Object<Args> + 'static>));
            ($ext_set)(Some(callback));
        }

        pub fn unset() {
            CALLBACK_KEY.replace(None);
            ($ext_set)(None);
        }

        extern "C" fn callback($($ext_arg: $ext_arg_ty),*) {
            match CALLBACK_KEY.get() {
                Some(cb) => unsafe { cb.call($call) },
                _ => {}
            }
        }
    )
)

pub mod error {
    use libc::{c_int, c_char};
    use std::mem;
    use std::string;

    callback!(
        type Args = (error: ::Error, description: String);
        type Callback = ErrorCallback;
        let ext_set = |cb| unsafe { ::ffi::glfwSetErrorCallback(cb) };
        fn callback(error: c_int, description: *const c_char) {
            (mem::transmute(error), string::String::from_raw_buf(
                description as *const u8))
        }
    )
}

pub mod monitor {
    use libc::{c_int};
    use std::mem;
    use std::kinds::marker;

    callback!(
        type Args = (monitor: ::Monitor, event: ::MonitorEvent);
        type Callback = MonitorCallback;
        let ext_set = |cb| unsafe { ::ffi::glfwSetMonitorCallback(cb) };
        fn callback(monitor: *mut ::ffi::GLFWmonitor, event: c_int) {
            let monitor = ::Monitor {
                ptr: monitor,
                no_copy: marker::NoCopy,
                no_send: marker::NoSend,
                no_share: marker::NoSync,
            };
            (monitor, mem::transmute(event))
        }
    )
}

unsafe fn get_sender<'a>(window: &'a *mut ffi::GLFWwindow) -> &'a Sender<(f64, WindowEvent)> {
    mem::transmute(ffi::glfwGetWindowUserPointer(*window))
}

macro_rules! window_callback(
    (fn $name:ident () => $event:ident) => (
        pub extern "C" fn $name(window: *mut ffi::GLFWwindow) {
            unsafe { get_sender(&window).send((ffi::glfwGetTime() as f64, WindowEvent::$event)); }
        }
     );
    (fn $name:ident ($($ext_arg:ident: $ext_arg_ty:ty),*) => $event:ident($($arg_conv:expr),*)) => (
        pub extern "C" fn $name(window: *mut ffi::GLFWwindow $(, $ext_arg: $ext_arg_ty)*) {
            unsafe { get_sender(&window).send((ffi::glfwGetTime() as f64, WindowEvent::$event($($arg_conv),*))); }
        }
     );
)

window_callback!(fn window_pos_callback(xpos: c_int, ypos: c_int)                           => PosEvent(xpos as i32, ypos as i32))
window_callback!(fn window_size_callback(width: c_int, height: c_int)                       => SizeEvent(width as i32, height as i32))
window_callback!(fn window_close_callback()                                                 => CloseEvent)
window_callback!(fn window_refresh_callback()                                               => RefreshEvent)
window_callback!(fn window_focus_callback(focused: c_int)                                   => FocusEvent(focused == ffi::TRUE))
window_callback!(fn window_iconify_callback(iconified: c_int)                               => IconifyEvent(iconified == ffi::TRUE))
window_callback!(fn framebuffer_size_callback(width: c_int, height: c_int)                  => FramebufferSizeEvent(width as i32, height as i32))
window_callback!(fn mouse_button_callback(button: c_int, action: c_int, mods: c_int)        => MouseButtonEvent(mem::transmute(button), mem::transmute(action), Modifiers::from_bits(mods).unwrap()))
window_callback!(fn cursor_pos_callback(xpos: c_double, ypos: c_double)                     => CursorPosEvent(xpos as f64, ypos as f64))
window_callback!(fn cursor_enter_callback(entered: c_int)                                   => CursorEnterEvent(entered == ffi::TRUE))
window_callback!(fn scroll_callback(xpos: c_double, ypos: c_double)                         => ScrollEvent(xpos as f64, ypos as f64))
window_callback!(fn key_callback(key: c_int, scancode: c_int, action: c_int, mods: c_int)   => KeyEvent(mem::transmute(key), scancode, mem::transmute(action), Modifiers::from_bits(mods).unwrap()))
window_callback!(fn char_callback(character: c_uint)                                        => CharEvent(::std::char::from_u32(character).unwrap()))
<|endoftext|>


<commit_before>#![cfg(feature = "reqwest-backend")]

use std::env::{remove_var, set_var};
use std::error::Error;
use std::net::TcpListener;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
use std::time::Duration;

use env_proxy::for_url;
use reqwest::{blocking::Client, Proxy};
use url::Url;

fn scrub_env() {
    remove_var("http_proxy");
    remove_var("https_proxy");
    remove_var("HTTPS_PROXY");
    remove_var("ftp_proxy");
    remove_var("FTP_PROXY");
    remove_var("all_proxy");
    remove_var("ALL_PROXY");
    remove_var("no_proxy");
    remove_var("NO_PROXY");
}

// Tests for correctly retrieving the proxy (host, port) tuple from $https_proxy
#[test]
fn read_basic_proxy_params() {
    scrub_env();
    set_var("https_proxy", "http://proxy.example.com:8080");
    let u = Url::parse("https://www.example.org").ok().unwrap();
    assert_eq!(
        for_url(&u).host_port(),
        Some(("proxy.example.com".to_string(), 8080))
    );
}

// Tests to verify if socks feature is available and being used
#[test]
fn socks_proxy_request() {
    static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);

    scrub_env();
    set_var("all_proxy", "socks5://127.0.0.1:1080");

    thread::spawn(move || {
        let listener = TcpListener::bind("127.0.0.1:1080").unwrap();
        let incoming = listener.incoming();
        for _ in incoming {
            CALL_COUNT.fetch_add(1, Ordering::SeqCst);
        }
    });

    let env_proxy = |url: &Url| for_url(&url).to_url();
    let url = Url::parse("http://example.org").unwrap();

    let client = Client::builder()
        .proxy(Proxy::custom(env_proxy))
        .timeout(Duration::from_secs(1))
        .build()
        .unwrap();
    let res = client.get(url.as_str()).send();

    if let Err(e) = res {
        let s = e.source().unwrap();
        assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
        assert!(s.to_string().contains("socks connect error"));
    } else {
        panic!("Socks proxy was ignored")
    }
}
<commit_msg>download: Serialise proxy environment tests<commit_after>#![cfg(feature = "reqwest-backend")]

use std::env::{remove_var, set_var};
use std::error::Error;
use std::net::TcpListener;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;
use std::thread;
use std::time::Duration;

use env_proxy::for_url;
use lazy_static::lazy_static;
use reqwest::{blocking::Client, Proxy};
use url::Url;

lazy_static! {
    static ref SERIALISE_TESTS: Mutex<()> = Mutex::new(());
}

fn scrub_env() {
    remove_var("http_proxy");
    remove_var("https_proxy");
    remove_var("HTTPS_PROXY");
    remove_var("ftp_proxy");
    remove_var("FTP_PROXY");
    remove_var("all_proxy");
    remove_var("ALL_PROXY");
    remove_var("no_proxy");
    remove_var("NO_PROXY");
}

// Tests for correctly retrieving the proxy (host, port) tuple from $https_proxy
#[test]
fn read_basic_proxy_params() {
    let _guard = SERIALISE_TESTS
        .lock()
        .expect("Unable to lock the test guard");
    scrub_env();
    set_var("https_proxy", "http://proxy.example.com:8080");
    let u = Url::parse("https://www.example.org").ok().unwrap();
    assert_eq!(
        for_url(&u).host_port(),
        Some(("proxy.example.com".to_string(), 8080))
    );
}

// Tests to verify if socks feature is available and being used
#[test]
fn socks_proxy_request() {
    static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
    let _guard = SERIALISE_TESTS
        .lock()
        .expect("Unable to lock the test guard");

    scrub_env();
    set_var("all_proxy", "socks5://127.0.0.1:1080");

    thread::spawn(move || {
        let listener = TcpListener::bind("127.0.0.1:1080").unwrap();
        let incoming = listener.incoming();
        for _ in incoming {
            CALL_COUNT.fetch_add(1, Ordering::SeqCst);
        }
    });

    let env_proxy = |url: &Url| for_url(&url).to_url();
    let url = Url::parse("http://example.org").unwrap();

    let client = Client::builder()
        .proxy(Proxy::custom(env_proxy))
        .timeout(Duration::from_secs(1))
        .build()
        .unwrap();
    let res = client.get(url.as_str()).send();

    if let Err(e) = res {
        let s = e.source().unwrap();
        assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
        assert!(s.to_string().contains("socks connect error"));
    } else {
        panic!("Socks proxy was ignored")
    }
}
<|endoftext|>


<commit_before>extern crate serialize;

use std::io::{fs,IoResult,Truncate,UserRWX,Write};
use std::io::fs::File;
use serialize::{Decodable,json};

#[deriving(Decodable,Show)]
struct Example {
    id: ~str,
    title: ~str,
}

fn read(file: &Path) -> IoResult<~str> {
    let mut file = try!(File::open(file));

    Ok(try!(file.read_to_str()))
}

fn write(file: &Path, contents: &str) -> IoResult<()> {
    let mut file = try!(File::open_mode(file, Truncate, Write));

    Ok(try!(file.write_str(contents)))
}

fn update(example: &Example) -> bool {
    print!("{}... ", example.id);

    let src_dir = Path::new(format!("src/{}", example.id));
    let out_dir = Path::new(format!("output/examples/{}", example.id));

    let sources: Vec<Path> = match fs::readdir(&src_dir) {
        Err(_) => {
            println!("couldn't read {}", src_dir.display());
            return false
        } Ok(contents) => contents.move_iter().filter(|path| match path.extension_str() {
            None => false,
            Some(extension) => extension == "rs",
        }).collect(),
    };

    if sources.is_empty() {
        println!("couldn't find source files");
        return false
    }

    let mut template = match read(&src_dir.join("input.md")) {
        Err(_) => {
            println!("couldn't read input.md");
            return false
        } Ok(contents) => format!("\\# {}\n\n{}", example.title, contents),
    };

    for source in sources.iter() {
        let filename = source.filename_str().unwrap();
        let code = match read(source) {
            Err(_) => { println!("couldn't read {}", filename); break },
            Ok(contents) => format!("``` rust\n// {}\n{}```", filename, contents),
        };

        template = template.replace(format!("\\{{}\\}", filename), code);
    }

    if !out_dir.exists() {
        fs::mkdir(&out_dir, UserRWX).unwrap();
    }

    match write(&out_dir.join("README.md"), template) {
        Err(_) => {
            println!("couldn't write README.md");
            false
        } Ok(_) => {
            println!("DONE");
            true
        }
    }
}

fn main() {
    let src_dir = Path::new("src");

    let examples: Vec<Example> = match read(&src_dir.join("order.json")) {
        Err(err) => fail!("couldn't read order.json: {}", err),
        Ok(string) => match json::from_str(string) {
            Err(err) => fail!("order.json is invalid json: {}", err),
            Ok(json) => match Decodable::decode(&mut json::Decoder::new(json)) {
                Err(err) => fail!("error decoding order.json: {}", err),
                Ok(data) => data,
            }
        }
    };

    let summary = examples.move_iter().map(|example| {
        if update(&example) {
            format!("* [{}](examples/{}/README.md)", example.title, example.id)
        } else {
            format!("* {}", example.title)
        }
    }).collect::<Vec<~str>>().connect("\n");

    if write(&Path::new("output/SUMMARY.md"), summary).is_err() {
        fail!("failed to write SUMMARY.md");
    }
}
<commit_msg>update.rs: process example even if there is no source file<commit_after>extern crate serialize;

use std::io::{fs,IoResult,Truncate,UserRWX,Write};
use std::io::fs::File;
use serialize::{Decodable,json};

#[deriving(Decodable,Show)]
struct Example {
    id: ~str,
    title: ~str,
}

fn read(file: &Path) -> IoResult<~str> {
    let mut file = try!(File::open(file));

    Ok(try!(file.read_to_str()))
}

fn write(file: &Path, contents: &str) -> IoResult<()> {
    let mut file = try!(File::open_mode(file, Truncate, Write));

    Ok(try!(file.write_str(contents)))
}

fn update(example: &Example) -> bool {
    print!("{}... ", example.id);

    let src_dir = Path::new(format!("src/{}", example.id));
    let out_dir = Path::new(format!("output/examples/{}", example.id));

    let sources: Vec<Path> = match fs::readdir(&src_dir) {
        Err(_) => {
            println!("couldn't read {}", src_dir.display());
            return false
        } Ok(contents) => contents.move_iter().filter(|path| match path.extension_str() {
            None => false,
            Some(extension) => extension == "rs",
        }).collect(),
    };

    let mut template = match read(&src_dir.join("input.md")) {
        Err(_) => {
            println!("couldn't read input.md");
            return false
        } Ok(contents) => format!("\\# {}\n\n{}", example.title, contents),
    };

    for source in sources.iter() {
        let filename = source.filename_str().unwrap();
        let code = match read(source) {
            Err(_) => { println!("couldn't read {}", filename); break },
            Ok(contents) => format!("``` rust\n// {}\n{}```", filename, contents),
        };

        template = template.replace(format!("\\{{}\\}", filename), code);
    }

    if !out_dir.exists() {
        fs::mkdir(&out_dir, UserRWX).unwrap();
    }

    match write(&out_dir.join("README.md"), template) {
        Err(_) => {
            println!("couldn't write README.md");
            false
        } Ok(_) => {
            println!("DONE");
            true
        }
    }
}

fn main() {
    let src_dir = Path::new("src");

    let examples: Vec<Example> = match read(&src_dir.join("order.json")) {
        Err(err) => fail!("couldn't read order.json: {}", err),
        Ok(string) => match json::from_str(string) {
            Err(err) => fail!("order.json is invalid json: {}", err),
            Ok(json) => match Decodable::decode(&mut json::Decoder::new(json)) {
                Err(err) => fail!("error decoding order.json: {}", err),
                Ok(data) => data,
            }
        }
    };

    let summary = examples.move_iter().map(|example| {
        if update(&example) {
            format!("* [{}](examples/{}/README.md)", example.title, example.id)
        } else {
            format!("* {}", example.title)
        }
    }).collect::<Vec<~str>>().connect("\n");

    if write(&Path::new("output/SUMMARY.md"), summary).is_err() {
        fail!("failed to write SUMMARY.md");
    }
}
<|endoftext|>


<commit_before>use std::ops::{
    Add,
    Sub,
    Mul,
    Div,
};

use num::{
    Zero,
};

macro_rules! impl_vec_self_binop {
    (impl $imp:ident, $method:ident for $vec:ident { $($field:ident),+ }) => {
        impl $imp for $vec {
            type Output = Self;

            #[inline]
            fn $method(self, other: Self) -> Self::Output {
                $vec { $($field: self.$field.$method(other.$field)),+ }
            }
        }
        ref_binop! { impl $imp, $method for $vec, $vec }
    }
}

macro_rules! impl_vec_self_binops {
    (impl $vec:ident { $($field:ident),+ }) => {
        impl_vec_self_binop! { impl Add, add for $vec { $($field),+ } }
        impl_vec_self_binop! { impl Sub, sub for $vec { $($field),+ } }
    }
}

macro_rules! impl_vec_float_binop {
    (impl $imp:ident, $method:ident for $vec:ident { $($field:ident),+ }) => {
        impl $imp<f32> for $vec {
            type Output = Self;

            #[inline]
            fn $method(self, other: f32) -> Self::Output {
                $vec { $($field: self.$field.$method(other)),+ }
            }
        }
        ref_binop! { impl $imp, $method for $vec, f32 }
    }
}

macro_rules! impl_vec_float_binops {
    (impl $vec:ident { $($field:ident),+ }) => {
        impl_vec_float_binop! { impl Add, add for $vec { $($field),+ } }
        impl_vec_float_binop! { impl Sub, sub for $vec { $($field),+ } }
        impl_vec_float_binop! { impl Div, div for $vec { $($field),+ } }
        impl_vec_float_binop! { impl Mul, mul for $vec { $($field),+ } }
    }
}

macro_rules! impl_vec_zero {
    (impl $vec:ident { $($field:ident),+ }) => {
        impl Zero for $vec {
            fn zero() -> Self {
                $vec { $($field: f32::zero()),+ }
            }

            fn is_zero(&self) -> bool {
                *self == Self::zero()
            }
        }
    }
}

macro_rules! impl_vec {
    ($vec:ident { $($field:ident),+ }) => {

        impl $vec {
            fn new($($field: f32),+) -> $vec {
                $vec { $($field: $field),+ }
            }
        }

        impl_vec_self_binops! { impl $vec { $($field),+ } }
        impl_vec_float_binops! { impl $vec { $($field),+ } }
        impl_vec_zero! { impl $vec { $($field),+ } }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec2 {
    pub x: f32,
    pub y: f32,
}
impl_vec! { Vec2 { x, y } }

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}
impl_vec! { Vec3 { x, y, z } }

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec4 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
    pub w: f32,
}
impl_vec! { Vec4 { x, y, z, w } }
<commit_msg>c repr for defined layout<commit_after>use std::ops::{
    Add,
    Sub,
    Mul,
    Div,
};

use num::{
    Zero,
};

macro_rules! impl_vec_self_binop {
    (impl $imp:ident, $method:ident for $vec:ident { $($field:ident),+ }) => {
        impl $imp for $vec {
            type Output = Self;

            #[inline]
            fn $method(self, other: Self) -> Self::Output {
                $vec { $($field: self.$field.$method(other.$field)),+ }
            }
        }
        ref_binop! { impl $imp, $method for $vec, $vec }
    }
}

macro_rules! impl_vec_self_binops {
    (impl $vec:ident { $($field:ident),+ }) => {
        impl_vec_self_binop! { impl Add, add for $vec { $($field),+ } }
        impl_vec_self_binop! { impl Sub, sub for $vec { $($field),+ } }
    }
}

macro_rules! impl_vec_float_binop {
    (impl $imp:ident, $method:ident for $vec:ident { $($field:ident),+ }) => {
        impl $imp<f32> for $vec {
            type Output = Self;

            #[inline]
            fn $method(self, other: f32) -> Self::Output {
                $vec { $($field: self.$field.$method(other)),+ }
            }
        }
        ref_binop! { impl $imp, $method for $vec, f32 }
    }
}

macro_rules! impl_vec_float_binops {
    (impl $vec:ident { $($field:ident),+ }) => {
        impl_vec_float_binop! { impl Add, add for $vec { $($field),+ } }
        impl_vec_float_binop! { impl Sub, sub for $vec { $($field),+ } }
        impl_vec_float_binop! { impl Div, div for $vec { $($field),+ } }
        impl_vec_float_binop! { impl Mul, mul for $vec { $($field),+ } }
    }
}

macro_rules! impl_vec_zero {
    (impl $vec:ident { $($field:ident),+ }) => {
        impl Zero for $vec {
            fn zero() -> Self {
                $vec { $($field: f32::zero()),+ }
            }

            fn is_zero(&self) -> bool {
                *self == Self::zero()
            }
        }
    }
}

macro_rules! impl_vec {
    ($vec:ident { $($field:ident),+ }) => {

        impl $vec {
            fn new($($field: f32),+) -> $vec {
                $vec { $($field: $field),+ }
            }
        }

        impl_vec_self_binops! { impl $vec { $($field),+ } }
        impl_vec_float_binops! { impl $vec { $($field),+ } }
        impl_vec_zero! { impl $vec { $($field),+ } }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec2 {
    pub x: f32,
    pub y: f32,
}
impl_vec! { Vec2 { x, y } }

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}
impl_vec! { Vec3 { x, y, z } }

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec4 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
    pub w: f32,
}
impl_vec! { Vec4 { x, y, z, w } }
<|endoftext|>


<commit_before>use std::sync::{Arc, Mutex};
use std::cmp;

use buffer::{Buffer, Anchor};
use geometry::{Point, Size};
use mode::{Command, Direction, Mode};
use buffer::{Display, Wrap};
use errors::{CrbResult, CrbError};
use state::State;
use logging;

pub struct Window {
    pub buf: Mutex<Buffer>,
    state: Arc<Mutex<State>>,

    /// Location on the screen.
    pub topleft: Point,
    pub size: Size,
    /// What line the top is at
    pub scroll: i32,

    pub mode: Mode,
    cursors: Vec<Anchor>,
    wrap: Wrap,
    index: i32,
}

fn do_with_state<F,T>(statelock: Arc<Mutex<State>>, func: F) -> T
        where F: Fn(&mut State) -> T {
    let mut state = statelock.lock().unwrap();
    let t = func(&mut *state);
    t
}

impl Window {
    pub fn new(buf: Mutex<Buffer>, topleft: Point, size: Size, state: Arc<Mutex<State>>) -> Window {
        let mut cursors = Vec::new();
        {
            let mut buf = buf.lock().unwrap();
            let a1 = buf.new_anchor();
            cursors.push(a1);
        }
        Window {
            buf: buf,
            index: do_with_state(state.clone(), |s| {
                let n = s.next_window_index;
                s.next_window_index += 1;
                n
            }),
            state: state,
            topleft: topleft,
            size: size,
            scroll: 0,
            cursors: cursors,
            mode: Mode::Normal,
            wrap: Wrap::default(size.width),
        }
    }

    pub fn save(&mut self) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        buf.save()
    }

    // pub fn line(&self, i: i32) -> &str {
    //     let mut buf = self.buf.lock().unwrap();
    //     let s = buf.line(i).map_or("", |s| s.to_owned());
    //     s
    // }

    pub fn title(&self) -> String {
        let buf = self.buf.lock().unwrap();
        let unsaved_prefix = match buf.unsaved {
            true => "*".to_string(),
            false => " ".to_string(),
        };
        let index = "[".to_string() + &self.index.to_string() + &"] ".to_string();
        let rest = match buf.file_path {
            Some(ref thing) => {
                match buf.newfile {
                    true => thing.clone() + &" (new file)".to_string(),
                    false => thing.clone(),
                }
            }
            None => "empty buffer".to_string(),
        };
        unsaved_prefix + &index + &rest
    }

    pub fn move_cursors(&mut self, m: &Command) -> CrbResult<()> {
        // TODO unlocking and then re-locking to call another method
        // probably has the wrong multi-threading guarantees.
        let delta = {
            let mut buf = self.buf.lock().unwrap();
            for anchor in self.cursors.iter() {
                // TODO: this is not good error handling.
                try!(buf.move_anchor(anchor, m));
            }
            let (dataline, wrapline) =
                try!(buf.get_anchor_line(self.cursors.last().unwrap(), &self.wrap));
            let bottom = self.scroll + self.size.height;
            // TODO: handle wrap
            logging::debug(&format!("{} {}", dataline, wrapline).to_owned());
            let up = cmp::min(0, dataline - self.scroll);
            let down = cmp::max(0, dataline - bottom + 2);
            let delta = up + down;
            delta
        };
        try!(self.scroll(&Command::Scroll(delta)));
        Ok(())
    }

    pub fn display<F>(&self, f: F)
        where F: FnMut(&Display)
    {
        let buf = self.buf.lock().unwrap();
        buf.display(self.scroll as usize, self.size, &self.wrap, f);
    }

    pub fn insert(&mut self, c: char) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        for anchor in self.cursors.iter() {
            try!(buf.insert_text_before(anchor, c));
        }
        Ok(())
    }

    pub fn insert_s(&mut self, s: &str) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        for c in s.chars() {
            for anchor in self.cursors.iter() {
                try!(buf.insert_text_before(anchor, c));
            }
        }
        Ok(())
    }

    pub fn clear(&mut self) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        buf.clear()
    }

    pub fn delete(&mut self, d: Direction) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        for anchor in self.cursors.iter() {
            try!(buf.delete_at(anchor, &d));
        }
        Ok(())
    }

    pub fn scroll(&mut self, c: &Command) -> CrbResult<()> {
        let buf = self.buf.lock().unwrap();
        if let Command::Scroll(n) = *c {
            self.scroll += n;
            // TODO this needs to happen whenever the buffer changes size.
            self.scroll = cmp::max(0, cmp::min(self.scroll, buf.count_lines()));
            Ok(())
        } else {
            Err(CrbError::new(&format!("invalid scroll command {:?}", c)))
        }
    }
}
<commit_msg>no cloning<commit_after>use std::sync::{Arc, Mutex};
use std::cmp;

use buffer::{Buffer, Anchor};
use geometry::{Point, Size};
use mode::{Command, Direction, Mode};
use buffer::{Display, Wrap};
use errors::{CrbResult, CrbError};
use state::State;
use logging;

pub struct Window {
    pub buf: Mutex<Buffer>,
    state: Arc<Mutex<State>>,

    /// Location on the screen.
    pub topleft: Point,
    pub size: Size,
    /// What line the top is at
    pub scroll: i32,

    pub mode: Mode,
    cursors: Vec<Anchor>,
    wrap: Wrap,
    index: i32,
}

fn do_with_state<F, T>(statelock: &Mutex<State>, func: F) -> T
    where F: Fn(&mut State) -> T
{
    let mut state = statelock.lock().unwrap();
    let t = func(&mut *state);
    t
}

impl Window {
    pub fn new(buf: Mutex<Buffer>, topleft: Point, size: Size, state: Arc<Mutex<State>>) -> Window {
        let mut cursors = Vec::new();
        {
            let mut buf = buf.lock().unwrap();
            let a1 = buf.new_anchor();
            cursors.push(a1);
        }
        Window {
            buf: buf,
            index: do_with_state(&*state, |s| {
                let n = s.next_window_index;
                s.next_window_index += 1;
                n
            }),
            state: state,
            topleft: topleft,
            size: size,
            scroll: 0,
            cursors: cursors,
            mode: Mode::Normal,
            wrap: Wrap::default(size.width),
        }
    }

    pub fn save(&mut self) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        buf.save()
    }

    // pub fn line(&self, i: i32) -> &str {
    //     let mut buf = self.buf.lock().unwrap();
    //     let s = buf.line(i).map_or("", |s| s.to_owned());
    //     s
    // }

    pub fn title(&self) -> String {
        let buf = self.buf.lock().unwrap();
        let unsaved_prefix = match buf.unsaved {
            true => "*".to_string(),
            false => " ".to_string(),
        };
        let index = "[".to_string() + &self.index.to_string() + &"] ".to_string();
        let rest = match buf.file_path {
            Some(ref thing) => {
                match buf.newfile {
                    true => thing.clone() + &" (new file)".to_string(),
                    false => thing.clone(),
                }
            }
            None => "empty buffer".to_string(),
        };
        unsaved_prefix + &index + &rest
    }

    pub fn move_cursors(&mut self, m: &Command) -> CrbResult<()> {
        // TODO unlocking and then re-locking to call another method
        // probably has the wrong multi-threading guarantees.
        let delta = {
            let mut buf = self.buf.lock().unwrap();
            for anchor in self.cursors.iter() {
                // TODO: this is not good error handling.
                try!(buf.move_anchor(anchor, m));
            }
            let (dataline, wrapline) =
                try!(buf.get_anchor_line(self.cursors.last().unwrap(), &self.wrap));
            let bottom = self.scroll + self.size.height;
            // TODO: handle wrap
            logging::debug(&format!("{} {}", dataline, wrapline).to_owned());
            let up = cmp::min(0, dataline - self.scroll);
            let down = cmp::max(0, dataline - bottom + 2);
            let delta = up + down;
            delta
        };
        try!(self.scroll(&Command::Scroll(delta)));
        Ok(())
    }

    pub fn display<F>(&self, f: F)
        where F: FnMut(&Display)
    {
        let buf = self.buf.lock().unwrap();
        buf.display(self.scroll as usize, self.size, &self.wrap, f);
    }

    pub fn insert(&mut self, c: char) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        for anchor in self.cursors.iter() {
            try!(buf.insert_text_before(anchor, c));
        }
        Ok(())
    }

    pub fn insert_s(&mut self, s: &str) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        for c in s.chars() {
            for anchor in self.cursors.iter() {
                try!(buf.insert_text_before(anchor, c));
            }
        }
        Ok(())
    }

    pub fn clear(&mut self) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        buf.clear()
    }

    pub fn delete(&mut self, d: Direction) -> CrbResult<()> {
        let mut buf = self.buf.lock().unwrap();
        for anchor in self.cursors.iter() {
            try!(buf.delete_at(anchor, &d));
        }
        Ok(())
    }

    pub fn scroll(&mut self, c: &Command) -> CrbResult<()> {
        let buf = self.buf.lock().unwrap();
        if let Command::Scroll(n) = *c {
            self.scroll += n;
            // TODO this needs to happen whenever the buffer changes size.
            self.scroll = cmp::max(0, cmp::min(self.scroll, buf.count_lines()));
            Ok(())
        } else {
            Err(CrbError::new(&format!("invalid scroll command {:?}", c)))
        }
    }
}
<|endoftext|>


<commit_before>use libsyntax2::{
    File, TextUnit, AstNode, SyntaxKind::*,
    ast::{self, LoopBodyOwner},
    algo::{
        ancestors,
        visit::{visitor, Visitor},
    },
    text_utils::is_subrange,
};

use {
    AtomEdit, find_node_at_offset,
    scope::{FnScopes, ModuleScope},
};

#[derive(Debug)]
pub struct CompletionItem {
    pub name: String,
    pub snippet: Option<String>
}

pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionItem>> {
    // Insert a fake ident to get a valid parse tree
    let file = {
        let edit = AtomEdit::insert(offset, "intellijRulezz".to_string());
        file.reparse(&edit)
    };
    let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), offset)?;
    if !is_single_segment(name_ref) {
        return None;
    }

    let mut res = Vec::new();
    if let Some(fn_def) = ancestors(name_ref.syntax()).filter_map(ast::FnDef::cast).next() {
        complete_expr_keywords(&file, fn_def, name_ref, &mut res);
        let scopes = FnScopes::new(fn_def);
        complete_fn(name_ref, &scopes, &mut res);
    }
    if let Some(root) = ancestors(name_ref.syntax()).filter_map(ast::Root::cast).next() {
        let scope = ModuleScope::new(root);
        res.extend(
            scope.entries().iter()
                .map(|entry| CompletionItem {
                    name: entry.name().to_string(),
                    snippet: None,
                })
        )
    }
    Some(res)
}

fn is_single_segment(name_ref: ast::NameRef) -> bool {
    match ancestors(name_ref.syntax()).filter_map(ast::Path::cast).next() {
        None => false,
        Some(path) => {
            path.syntax().range() == name_ref.syntax().range()
        }
    }
}

fn complete_expr_keywords(file: &File, fn_def: ast::FnDef, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) {
    acc.push(keyword("if", "if $0 { }"));
    acc.push(keyword("match", "match $0 { }"));
    acc.push(keyword("while", "while $0 { }"));
    acc.push(keyword("loop", "loop {$0}"));

    if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
        if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
            if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
                acc.push(keyword("else", "else {$0}"));
                acc.push(keyword("else if", "else if $0 { }"));
            }
        }
    }
    if is_in_loop_body(name_ref) {
        acc.push(keyword("continue", "continue"));
        acc.push(keyword("break", "break"));
    }
    acc.extend(complete_return(fn_def, name_ref));
}

fn is_in_loop_body(name_ref: ast::NameRef) -> bool {
    for node in ancestors(name_ref.syntax()) {
        if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
            break;
        }
        let loop_body = visitor()
            .visit::<ast::ForExpr, _>(LoopBodyOwner::loop_body)
            .visit::<ast::WhileExpr, _>(LoopBodyOwner::loop_body)
            .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
            .accept(node);
        if let Some(Some(body)) = loop_body {
            if is_subrange(body.syntax().range(), name_ref.syntax().range()) {
                return true;
            }
        }
    }
    false
}

fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option<CompletionItem> {
    // let is_last_in_block = ancestors(name_ref.syntax()).filter_map(ast::Expr::cast)
    //     .next()
    //     .and_then(|it| it.syntax().parent())
    //     .and_then(ast::Block::cast)
    //     .is_some();

    // if is_last_in_block {
    //     return None;
    // }

    let is_stmt = match ancestors(name_ref.syntax()).filter_map(ast::ExprStmt::cast).next() {
        None => false,
        Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range()
    };
    let snip = match (is_stmt, fn_def.ret_type().is_some()) {
        (true, true) => "return $0;",
        (true, false) => "return;",
        (false, true) => "return $0",
        (false, false) => "return",
    };
    Some(keyword("return", snip))
}

fn keyword(kw: &str, snip: &str) -> CompletionItem {
    CompletionItem {
        name: kw.to_string(),
        snippet: Some(snip.to_string()),
    }
}

fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
    acc.extend(
        scopes.scope_chain(name_ref.syntax())
            .flat_map(|scope| scopes.entries(scope).iter())
            .map(|entry| CompletionItem {
                name: entry.name().to_string(),
                snippet: None,
            })
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use test_utils::{assert_eq_dbg, extract_offset};

    fn check_scope_completion(code: &str, expected_completions: &str) {
        let (off, code) = extract_offset(&code);
        let file = File::parse(&code);
        let completions = scope_completion(&file, off)
            .unwrap()
            .into_iter()
            .filter(|c| c.snippet.is_none())
            .collect::<Vec<_>>();
        assert_eq_dbg(expected_completions, &completions);
    }

    fn check_snippet_completion(code: &str, expected_completions: &str) {
        let (off, code) = extract_offset(&code);
        let file = File::parse(&code);
        let completions = scope_completion(&file, off)
            .unwrap()
            .into_iter()
            .filter(|c| c.snippet.is_some())
            .collect::<Vec<_>>();
        assert_eq_dbg(expected_completions, &completions);
    }

    #[test]
    fn test_completion_let_scope() {
        check_scope_completion(r"
            fn quux(x: i32) {
                let y = 92;
                1 + <|>;
                let z = ();
            }
            ", r#"[CompletionItem { name: "y", snippet: None },
                   CompletionItem { name: "x", snippet: None },
                   CompletionItem { name: "quux", snippet: None }]"#);
    }

    #[test]
    fn test_completion_if_let_scope() {
        check_scope_completion(r"
            fn quux() {
                if let Some(x) = foo() {
                    let y = 92;
                };
                if let Some(a) = bar() {
                    let b = 62;
                    1 + <|>
                }
            }
            ", r#"[CompletionItem { name: "b", snippet: None },
                   CompletionItem { name: "a", snippet: None },
                   CompletionItem { name: "quux", snippet: None }]"#);
    }

    #[test]
    fn test_completion_for_scope() {
        check_scope_completion(r"
            fn quux() {
                for x in &[1, 2, 3] {
                    <|>
                }
            }
            ", r#"[CompletionItem { name: "x", snippet: None },
                   CompletionItem { name: "quux", snippet: None }]"#);
    }

    #[test]
    fn test_completion_mod_scope() {
        check_scope_completion(r"
            struct Foo;
            enum Baz {}
            fn quux() {
                <|>
            }
            ", r#"[CompletionItem { name: "Foo", snippet: None },
                   CompletionItem { name: "Baz", snippet: None },
                   CompletionItem { name: "quux", snippet: None }]"#);
    }

    #[test]
    fn test_complete_type() {
        check_scope_completion(r"
            struct Foo;
            fn x() -> <|>
        ", r#"[CompletionItem { name: "Foo", snippet: None },
               CompletionItem { name: "x", snippet: None }]"#)
    }

    #[test]
    fn test_completion_kewords() {
        check_snippet_completion(r"
            fn quux() {
                <|>
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "return", snippet: Some("return") }]"#);
    }

    #[test]
    fn test_completion_else() {
        check_snippet_completion(r"
            fn quux() {
                if true {
                    ()
                } <|>
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "else", snippet: Some("else {$0}") },
                   CompletionItem { name: "else if", snippet: Some("else if $0 { }") },
                   CompletionItem { name: "return", snippet: Some("return") }]"#);
    }

    #[test]
    fn test_completion_return_value() {
        check_snippet_completion(r"
            fn quux() -> i32 {
                <|>
                92
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "return", snippet: Some("return $0;") }]"#);
        check_snippet_completion(r"
            fn quux() {
                <|>
                92
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "return", snippet: Some("return;") }]"#);
    }

    #[test]
    fn test_completion_return_no_stmt() {
        check_snippet_completion(r"
            fn quux() -> i32 {
                match () {
                    () => <|>
                }
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "return", snippet: Some("return $0") }]"#);
    }

    #[test]
    fn test_continue_break_completion() {
        check_snippet_completion(r"
            fn quux() -> i32 {
                loop { <|> }
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "continue", snippet: Some("continue") },
                   CompletionItem { name: "break", snippet: Some("break") },
                   CompletionItem { name: "return", snippet: Some("return $0") }]"#);
    }
}
<commit_msg>add test<commit_after>use libsyntax2::{
    File, TextUnit, AstNode, SyntaxKind::*,
    ast::{self, LoopBodyOwner},
    algo::{
        ancestors,
        visit::{visitor, Visitor},
    },
    text_utils::is_subrange,
};

use {
    AtomEdit, find_node_at_offset,
    scope::{FnScopes, ModuleScope},
};

#[derive(Debug)]
pub struct CompletionItem {
    pub name: String,
    pub snippet: Option<String>
}

pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionItem>> {
    // Insert a fake ident to get a valid parse tree
    let file = {
        let edit = AtomEdit::insert(offset, "intellijRulezz".to_string());
        file.reparse(&edit)
    };
    let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), offset)?;
    if !is_single_segment(name_ref) {
        return None;
    }

    let mut res = Vec::new();
    if let Some(fn_def) = ancestors(name_ref.syntax()).filter_map(ast::FnDef::cast).next() {
        complete_expr_keywords(&file, fn_def, name_ref, &mut res);
        let scopes = FnScopes::new(fn_def);
        complete_fn(name_ref, &scopes, &mut res);
    }
    if let Some(root) = ancestors(name_ref.syntax()).filter_map(ast::Root::cast).next() {
        let scope = ModuleScope::new(root);
        res.extend(
            scope.entries().iter()
                .map(|entry| CompletionItem {
                    name: entry.name().to_string(),
                    snippet: None,
                })
        )
    }
    Some(res)
}

fn is_single_segment(name_ref: ast::NameRef) -> bool {
    match ancestors(name_ref.syntax()).filter_map(ast::Path::cast).next() {
        None => false,
        Some(path) => {
            path.syntax().range() == name_ref.syntax().range()
        }
    }
}

fn complete_expr_keywords(file: &File, fn_def: ast::FnDef, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) {
    acc.push(keyword("if", "if $0 { }"));
    acc.push(keyword("match", "match $0 { }"));
    acc.push(keyword("while", "while $0 { }"));
    acc.push(keyword("loop", "loop {$0}"));

    if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
        if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
            if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
                acc.push(keyword("else", "else {$0}"));
                acc.push(keyword("else if", "else if $0 { }"));
            }
        }
    }
    if is_in_loop_body(name_ref) {
        acc.push(keyword("continue", "continue"));
        acc.push(keyword("break", "break"));
    }
    acc.extend(complete_return(fn_def, name_ref));
}

fn is_in_loop_body(name_ref: ast::NameRef) -> bool {
    for node in ancestors(name_ref.syntax()) {
        if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
            break;
        }
        let loop_body = visitor()
            .visit::<ast::ForExpr, _>(LoopBodyOwner::loop_body)
            .visit::<ast::WhileExpr, _>(LoopBodyOwner::loop_body)
            .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
            .accept(node);
        if let Some(Some(body)) = loop_body {
            if is_subrange(body.syntax().range(), name_ref.syntax().range()) {
                return true;
            }
        }
    }
    false
}

fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option<CompletionItem> {
    // let is_last_in_block = ancestors(name_ref.syntax()).filter_map(ast::Expr::cast)
    //     .next()
    //     .and_then(|it| it.syntax().parent())
    //     .and_then(ast::Block::cast)
    //     .is_some();

    // if is_last_in_block {
    //     return None;
    // }

    let is_stmt = match ancestors(name_ref.syntax()).filter_map(ast::ExprStmt::cast).next() {
        None => false,
        Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range()
    };
    let snip = match (is_stmt, fn_def.ret_type().is_some()) {
        (true, true) => "return $0;",
        (true, false) => "return;",
        (false, true) => "return $0",
        (false, false) => "return",
    };
    Some(keyword("return", snip))
}

fn keyword(kw: &str, snip: &str) -> CompletionItem {
    CompletionItem {
        name: kw.to_string(),
        snippet: Some(snip.to_string()),
    }
}

fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
    acc.extend(
        scopes.scope_chain(name_ref.syntax())
            .flat_map(|scope| scopes.entries(scope).iter())
            .map(|entry| CompletionItem {
                name: entry.name().to_string(),
                snippet: None,
            })
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use test_utils::{assert_eq_dbg, extract_offset};

    fn check_scope_completion(code: &str, expected_completions: &str) {
        let (off, code) = extract_offset(&code);
        let file = File::parse(&code);
        let completions = scope_completion(&file, off)
            .unwrap()
            .into_iter()
            .filter(|c| c.snippet.is_none())
            .collect::<Vec<_>>();
        assert_eq_dbg(expected_completions, &completions);
    }

    fn check_snippet_completion(code: &str, expected_completions: &str) {
        let (off, code) = extract_offset(&code);
        let file = File::parse(&code);
        let completions = scope_completion(&file, off)
            .unwrap()
            .into_iter()
            .filter(|c| c.snippet.is_some())
            .collect::<Vec<_>>();
        assert_eq_dbg(expected_completions, &completions);
    }

    #[test]
    fn test_completion_let_scope() {
        check_scope_completion(r"
            fn quux(x: i32) {
                let y = 92;
                1 + <|>;
                let z = ();
            }
            ", r#"[CompletionItem { name: "y", snippet: None },
                   CompletionItem { name: "x", snippet: None },
                   CompletionItem { name: "quux", snippet: None }]"#);
    }

    #[test]
    fn test_completion_if_let_scope() {
        check_scope_completion(r"
            fn quux() {
                if let Some(x) = foo() {
                    let y = 92;
                };
                if let Some(a) = bar() {
                    let b = 62;
                    1 + <|>
                }
            }
            ", r#"[CompletionItem { name: "b", snippet: None },
                   CompletionItem { name: "a", snippet: None },
                   CompletionItem { name: "quux", snippet: None }]"#);
    }

    #[test]
    fn test_completion_for_scope() {
        check_scope_completion(r"
            fn quux() {
                for x in &[1, 2, 3] {
                    <|>
                }
            }
            ", r#"[CompletionItem { name: "x", snippet: None },
                   CompletionItem { name: "quux", snippet: None }]"#);
    }

    #[test]
    fn test_completion_mod_scope() {
        check_scope_completion(r"
            struct Foo;
            enum Baz {}
            fn quux() {
                <|>
            }
            ", r#"[CompletionItem { name: "Foo", snippet: None },
                   CompletionItem { name: "Baz", snippet: None },
                   CompletionItem { name: "quux", snippet: None }]"#);
    }

    #[test]
    fn test_complete_type() {
        check_scope_completion(r"
            struct Foo;
            fn x() -> <|>
        ", r#"[CompletionItem { name: "Foo", snippet: None },
               CompletionItem { name: "x", snippet: None }]"#)
    }

    #[test]
    fn test_completion_kewords() {
        check_snippet_completion(r"
            fn quux() {
                <|>
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "return", snippet: Some("return") }]"#);
    }

    #[test]
    fn test_completion_else() {
        check_snippet_completion(r"
            fn quux() {
                if true {
                    ()
                } <|>
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "else", snippet: Some("else {$0}") },
                   CompletionItem { name: "else if", snippet: Some("else if $0 { }") },
                   CompletionItem { name: "return", snippet: Some("return") }]"#);
    }

    #[test]
    fn test_completion_return_value() {
        check_snippet_completion(r"
            fn quux() -> i32 {
                <|>
                92
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "return", snippet: Some("return $0;") }]"#);
        check_snippet_completion(r"
            fn quux() {
                <|>
                92
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "return", snippet: Some("return;") }]"#);
    }

    #[test]
    fn test_completion_return_no_stmt() {
        check_snippet_completion(r"
            fn quux() -> i32 {
                match () {
                    () => <|>
                }
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "return", snippet: Some("return $0") }]"#);
    }

    #[test]
    fn test_continue_break_completion() {
        check_snippet_completion(r"
            fn quux() -> i32 {
                loop { <|> }
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "continue", snippet: Some("continue") },
                   CompletionItem { name: "break", snippet: Some("break") },
                   CompletionItem { name: "return", snippet: Some("return $0") }]"#);
        check_snippet_completion(r"
            fn quux() -> i32 {
                loop { || { <|> } }
            }
            ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") },
                   CompletionItem { name: "match", snippet: Some("match $0 { }") },
                   CompletionItem { name: "while", snippet: Some("while $0 { }") },
                   CompletionItem { name: "loop", snippet: Some("loop {$0}") },
                   CompletionItem { name: "return", snippet: Some("return $0") }]"#);
    }
}
<|endoftext|>


<commit_before>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types for [Matrix](https://matrix.org/) identifiers for devices, events, keys, rooms, servers,
//! users and URIs.

#![warn(missing_docs)]
// FIXME: Remove once lint doesn't trigger on std::convert::TryFrom in macros.rs anymore
#![allow(unused_qualifications)]
#![cfg_attr(docsrs, feature(doc_cfg))]

// Renamed in `Cargo.toml` so we can have a serde feature.
// Rename it back here because `serde1` is ugly.
#[cfg(feature = "serde")]
extern crate serde1 as serde;

#[cfg(feature = "serde")]
use std::convert::TryFrom;

#[cfg(feature = "serde")]
use serde::de::{self, Deserializer, Unexpected};

#[doc(inline)]
pub use crate::{
    crypto_algorithms::{DeviceKeyAlgorithm, EventEncryptionAlgorithm, SigningKeyAlgorithm},
    device_key_id::DeviceKeyId,
    event_id::EventId,
    key_id::{DeviceSigningKeyId, KeyId, ServerSigningKeyId, SigningKeyId},
    mxc_uri::MxcUri,
    opaque_ids::{DeviceId, DeviceIdBox, KeyName, KeyNameBox},
    room_alias_id::RoomAliasId,
    room_id::RoomId,
    room_id_or_room_alias_id::RoomIdOrAliasId,
    room_version_id::RoomVersionId,
    server_name::{ServerName, ServerNameBox},
    signatures::{DeviceSignatures, EntitySignatures, ServerSignatures, Signatures},
    user_id::UserId,
};
#[doc(inline)]
pub use ruma_identifiers_validation::error::Error;

#[macro_use]
mod macros;

pub mod user_id;

mod crypto_algorithms;
mod device_key_id;
mod event_id;
mod key_id;
mod mxc_uri;
mod opaque_ids;
mod room_alias_id;
mod room_id;
mod room_id_or_room_alias_id;
mod room_version_id;
mod server_name;
mod signatures;

/// Check whether a given string is a valid server name according to [the specification][].
///
/// [the specification]: https://matrix.org/docs/spec/appendices#server-name
#[deprecated = "Use the [`ServerName`](server_name/struct.ServerName.html) type instead."]
pub fn is_valid_server_name(name: &str) -> bool {
    <&ServerName>::try_from(name).is_ok()
}

/// Generates a random identifier localpart.
#[cfg(feature = "rand")]
fn generate_localpart(length: usize) -> Box<str> {
    use rand::Rng as _;
    rand::thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .map(char::from)
        .take(length)
        .collect::<String>()
        .into_boxed_str()
}

/// Deserializes any type of id using the provided TryFrom implementation.
///
/// This is a helper function to reduce the boilerplate of the Deserialize implementations.
#[cfg(feature = "serde")]
fn deserialize_id<'de, D, T>(deserializer: D, expected_str: &str) -> Result<T, D::Error>
where
    D: Deserializer<'de>,
    T: for<'a> TryFrom<&'a str>,
{
    ruma_serde::deserialize_cow_str(deserializer).and_then(|v| {
        T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str))
    })
}

/// Shorthand for `Box::<DeviceId>::from`.
#[macro_export]
macro_rules! device_id {
    ($s:tt) => {
        ::std::boxed::Box::<$crate::DeviceId>::from($s)
    };
}

// A plain re-export shows up in rustdoc despite doc(hidden). Use a module instead.
// Bug report: https://github.com/rust-lang/rust/issues/83939
#[doc(hidden)]
pub mod _macros {
    pub use ruma_identifiers_macros::*;
}

/// Compile-time checked `DeviceKeyId` construction.
#[macro_export]
macro_rules! device_key_id {
    ($s:literal) => {
        $crate::_macros::device_key_id!($crate, $s)
    };
}

/// Compile-time checked `EventId` construction.
#[macro_export]
macro_rules! event_id {
    ($s:literal) => {
        $crate::_macros::event_id!($crate, $s)
    };
}

/// Compile-time checked `RoomAliasId` construction.
#[macro_export]
macro_rules! room_alias_id {
    ($s:literal) => {
        $crate::_macros::room_alias_id!($crate, $s)
    };
}

/// Compile-time checked `RoomId` construction.
#[macro_export]
macro_rules! room_id {
    ($s:literal) => {
        $crate::_macros::room_id!($crate, $s)
    };
}

/// Compile-time checked `RoomVersionId` construction.
#[macro_export]
macro_rules! room_version_id {
    ($s:literal) => {
        $crate::_macros::room_version_id!($crate, $s)
    };
}

/// Compile-time checked `ServerSigningKeyId` construction.
#[macro_export]
#[deprecated = "use server_signing_key_id!()"]
macro_rules! server_key_id {
    ($s:literal) => {
        $crate::_macros::server_signing_key_id!($crate, $s)
    };
}

/// Compile-time checked `ServerSigningKeyId` construction.
#[macro_export]
macro_rules! server_signing_key_id {
    ($s:literal) => {
        $crate::_macros::server_signing_key_id!($crate, $s)
    };
}

/// Compile-time checked `ServerName` construction.
#[macro_export]
macro_rules! server_name {
    ($s:literal) => {
        $crate::_macros::server_name!($crate, $s)
    };
}

/// Compile-time checked `MxcUri` construction.
#[macro_export]
macro_rules! mxc_uri {
    ($s:literal) => {
        $crate::_macros::mxc_uri!($crate, $s)
    };
}

/// Compile-time checked `UserId` construction.
#[macro_export]
macro_rules! user_id {
    ($s:literal) => {
        $crate::_macros::user_id!($crate, $s)
    };
}
<commit_msg>Revert "identifiers: Fix unused import without serde feature"<commit_after>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types for [Matrix](https://matrix.org/) identifiers for devices, events, keys, rooms, servers,
//! users and URIs.

#![warn(missing_docs)]
// FIXME: Remove once lint doesn't trigger on std::convert::TryFrom in macros.rs anymore
#![allow(unused_qualifications)]
#![cfg_attr(docsrs, feature(doc_cfg))]

// Renamed in `Cargo.toml` so we can have a serde feature.
// Rename it back here because `serde1` is ugly.
#[cfg(feature = "serde")]
extern crate serde1 as serde;

use std::convert::TryFrom;

#[cfg(feature = "serde")]
use serde::de::{self, Deserializer, Unexpected};

#[doc(inline)]
pub use crate::{
    crypto_algorithms::{DeviceKeyAlgorithm, EventEncryptionAlgorithm, SigningKeyAlgorithm},
    device_key_id::DeviceKeyId,
    event_id::EventId,
    key_id::{DeviceSigningKeyId, KeyId, ServerSigningKeyId, SigningKeyId},
    mxc_uri::MxcUri,
    opaque_ids::{DeviceId, DeviceIdBox, KeyName, KeyNameBox},
    room_alias_id::RoomAliasId,
    room_id::RoomId,
    room_id_or_room_alias_id::RoomIdOrAliasId,
    room_version_id::RoomVersionId,
    server_name::{ServerName, ServerNameBox},
    signatures::{DeviceSignatures, EntitySignatures, ServerSignatures, Signatures},
    user_id::UserId,
};
#[doc(inline)]
pub use ruma_identifiers_validation::error::Error;

#[macro_use]
mod macros;

pub mod user_id;

mod crypto_algorithms;
mod device_key_id;
mod event_id;
mod key_id;
mod mxc_uri;
mod opaque_ids;
mod room_alias_id;
mod room_id;
mod room_id_or_room_alias_id;
mod room_version_id;
mod server_name;
mod signatures;

/// Check whether a given string is a valid server name according to [the specification][].
///
/// [the specification]: https://matrix.org/docs/spec/appendices#server-name
#[deprecated = "Use the [`ServerName`](server_name/struct.ServerName.html) type instead."]
pub fn is_valid_server_name(name: &str) -> bool {
    <&ServerName>::try_from(name).is_ok()
}

/// Generates a random identifier localpart.
#[cfg(feature = "rand")]
fn generate_localpart(length: usize) -> Box<str> {
    use rand::Rng as _;
    rand::thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .map(char::from)
        .take(length)
        .collect::<String>()
        .into_boxed_str()
}

/// Deserializes any type of id using the provided TryFrom implementation.
///
/// This is a helper function to reduce the boilerplate of the Deserialize implementations.
#[cfg(feature = "serde")]
fn deserialize_id<'de, D, T>(deserializer: D, expected_str: &str) -> Result<T, D::Error>
where
    D: Deserializer<'de>,
    T: for<'a> TryFrom<&'a str>,
{
    ruma_serde::deserialize_cow_str(deserializer).and_then(|v| {
        T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str))
    })
}

/// Shorthand for `Box::<DeviceId>::from`.
#[macro_export]
macro_rules! device_id {
    ($s:tt) => {
        ::std::boxed::Box::<$crate::DeviceId>::from($s)
    };
}

// A plain re-export shows up in rustdoc despite doc(hidden). Use a module instead.
// Bug report: https://github.com/rust-lang/rust/issues/83939
#[doc(hidden)]
pub mod _macros {
    pub use ruma_identifiers_macros::*;
}

/// Compile-time checked `DeviceKeyId` construction.
#[macro_export]
macro_rules! device_key_id {
    ($s:literal) => {
        $crate::_macros::device_key_id!($crate, $s)
    };
}

/// Compile-time checked `EventId` construction.
#[macro_export]
macro_rules! event_id {
    ($s:literal) => {
        $crate::_macros::event_id!($crate, $s)
    };
}

/// Compile-time checked `RoomAliasId` construction.
#[macro_export]
macro_rules! room_alias_id {
    ($s:literal) => {
        $crate::_macros::room_alias_id!($crate, $s)
    };
}

/// Compile-time checked `RoomId` construction.
#[macro_export]
macro_rules! room_id {
    ($s:literal) => {
        $crate::_macros::room_id!($crate, $s)
    };
}

/// Compile-time checked `RoomVersionId` construction.
#[macro_export]
macro_rules! room_version_id {
    ($s:literal) => {
        $crate::_macros::room_version_id!($crate, $s)
    };
}

/// Compile-time checked `ServerSigningKeyId` construction.
#[macro_export]
#[deprecated = "use server_signing_key_id!()"]
macro_rules! server_key_id {
    ($s:literal) => {
        $crate::_macros::server_signing_key_id!($crate, $s)
    };
}

/// Compile-time checked `ServerSigningKeyId` construction.
#[macro_export]
macro_rules! server_signing_key_id {
    ($s:literal) => {
        $crate::_macros::server_signing_key_id!($crate, $s)
    };
}

/// Compile-time checked `ServerName` construction.
#[macro_export]
macro_rules! server_name {
    ($s:literal) => {
        $crate::_macros::server_name!($crate, $s)
    };
}

/// Compile-time checked `MxcUri` construction.
#[macro_export]
macro_rules! mxc_uri {
    ($s:literal) => {
        $crate::_macros::mxc_uri!($crate, $s)
    };
}

/// Compile-time checked `UserId` construction.
#[macro_export]
macro_rules! user_id {
    ($s:literal) => {
        $crate::_macros::user_id!($crate, $s)
    };
}
<|endoftext|>