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

//! Collection types.
//!
//! See [std::collections](../std/collections) for a detailed discussion of collections in Rust.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "collections"]
#![unstable(feature = "collections")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(core)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag)]
#![cfg_attr(test, feature(rand, rustc_private, test))]
#![cfg_attr(test, allow(deprecated))] // rand

#![feature(no_std)]
#![no_std]

#[macro_use]
extern crate core;

extern crate unicode;
extern crate alloc;

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate std;
#[cfg(test)] #[macro_use] extern crate log;

pub use binary_heap::BinaryHeap;
pub use bit_vec::BitVec;
pub use bit_set::BitSet;
pub use btree_map::BTreeMap;
pub use btree_set::BTreeSet;
pub use linked_list::LinkedList;
pub use enum_set::EnumSet;
pub use vec_deque::VecDeque;
pub use string::String;
pub use vec::Vec;
pub use vec_map::VecMap;

#[deprecated(since = "1.0.0", reason = "renamed to vec_deque")]
#[unstable(feature = "collections")]
pub use vec_deque as ring_buf;

#[deprecated(since = "1.0.0", reason = "renamed to linked_list")]
#[unstable(feature = "collections")]
pub use linked_list as dlist;

#[deprecated(since = "1.0.0", reason = "renamed to bit_vec")]
#[unstable(feature = "collections")]
pub use bit_vec as bitv;

#[deprecated(since = "1.0.0", reason = "renamed to bit_set")]
#[unstable(feature = "collections")]
pub use bit_set as bitv_set;

// Needed for the vec! macro
pub use alloc::boxed;

#[macro_use]
mod macros;

#[cfg(test)] #[macro_use] mod bench;

pub mod binary_heap;
mod bit;
mod btree;
pub mod borrow;
pub mod enum_set;
pub mod fmt;
pub mod linked_list;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;
pub mod vec_deque;
pub mod vec_map;

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bit_vec {
    pub use bit::{BitVec, Iter};

    #[deprecated(since = "1.0.0", reason = "renamed to BitVec")]
    #[unstable(feature = "collections")]
    pub use bit::BitVec as Bitv;
}

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bit_set {
    pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
    pub use bit::SetIter as Iter;

    #[deprecated(since = "1.0.0", reason = "renamed to BitSet")]
    #[unstable(feature = "collections")]
    pub use bit::BitSet as BitvSet;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_map {
    pub use btree::map::*;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_set {
    pub use btree::set::*;
}

// FIXME(#14344) this shouldn't be necessary
#[doc(hidden)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}

#[cfg(not(test))]
mod std {
    pub use core::ops;      // RangeFull
}

#[cfg(test)]
mod prelude {
    // from core.
    pub use core::clone::Clone;
    pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
    pub use core::cmp::Ordering::{Less, Equal, Greater};
    pub use core::iter::range;
    pub use core::iter::{FromIterator, Extend, IteratorExt};
    pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator};
    pub use core::iter::{ExactSizeIterator};
    pub use core::marker::{Copy, Send, Sized, Sync};
    pub use core::mem::drop;
    pub use core::ops::{Drop, Fn, FnMut, FnOnce};
    pub use core::option::Option;
    pub use core::option::Option::{Some, None};
    pub use core::ptr::PtrExt;
    pub use core::result::Result;
    pub use core::result::Result::{Ok, Err};

    // in core and collections (may differ).
    pub use slice::{AsSlice, SliceExt};
    pub use str::{Str, StrExt};

    // from other crates.
    pub use alloc::boxed::Box;
    pub use unicode::char::CharExt;

    // from collections.
    pub use borrow::IntoCow;
    pub use slice::SliceConcatExt;
    pub use string::{String, ToString};
    pub use vec::Vec;
}

/// An endpoint of a range of keys.
pub enum Bound<T> {
    /// An inclusive bound.
    Included(T),
    /// An exclusive bound.
    Excluded(T),
    /// An infinite endpoint. Indicates that there is no bound in this direction.
    Unbounded,
}
<commit_msg>derive common traits for `collections::Bound`<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Collection types.
//!
//! See [std::collections](../std/collections) for a detailed discussion of collections in Rust.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "collections"]
#![unstable(feature = "collections")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(core)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag)]
#![cfg_attr(test, feature(rand, rustc_private, test))]
#![cfg_attr(test, allow(deprecated))] // rand

#![feature(no_std)]
#![no_std]

#[macro_use]
extern crate core;

extern crate unicode;
extern crate alloc;

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate std;
#[cfg(test)] #[macro_use] extern crate log;

pub use binary_heap::BinaryHeap;
pub use bit_vec::BitVec;
pub use bit_set::BitSet;
pub use btree_map::BTreeMap;
pub use btree_set::BTreeSet;
pub use linked_list::LinkedList;
pub use enum_set::EnumSet;
pub use vec_deque::VecDeque;
pub use string::String;
pub use vec::Vec;
pub use vec_map::VecMap;

#[deprecated(since = "1.0.0", reason = "renamed to vec_deque")]
#[unstable(feature = "collections")]
pub use vec_deque as ring_buf;

#[deprecated(since = "1.0.0", reason = "renamed to linked_list")]
#[unstable(feature = "collections")]
pub use linked_list as dlist;

#[deprecated(since = "1.0.0", reason = "renamed to bit_vec")]
#[unstable(feature = "collections")]
pub use bit_vec as bitv;

#[deprecated(since = "1.0.0", reason = "renamed to bit_set")]
#[unstable(feature = "collections")]
pub use bit_set as bitv_set;

// Needed for the vec! macro
pub use alloc::boxed;

#[macro_use]
mod macros;

#[cfg(test)] #[macro_use] mod bench;

pub mod binary_heap;
mod bit;
mod btree;
pub mod borrow;
pub mod enum_set;
pub mod fmt;
pub mod linked_list;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;
pub mod vec_deque;
pub mod vec_map;

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bit_vec {
    pub use bit::{BitVec, Iter};

    #[deprecated(since = "1.0.0", reason = "renamed to BitVec")]
    #[unstable(feature = "collections")]
    pub use bit::BitVec as Bitv;
}

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bit_set {
    pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
    pub use bit::SetIter as Iter;

    #[deprecated(since = "1.0.0", reason = "renamed to BitSet")]
    #[unstable(feature = "collections")]
    pub use bit::BitSet as BitvSet;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_map {
    pub use btree::map::*;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_set {
    pub use btree::set::*;
}

// FIXME(#14344) this shouldn't be necessary
#[doc(hidden)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}

#[cfg(not(test))]
mod std {
    pub use core::ops;      // RangeFull
}

#[cfg(test)]
mod prelude {
    // from core.
    pub use core::clone::Clone;
    pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
    pub use core::cmp::Ordering::{Less, Equal, Greater};
    pub use core::iter::range;
    pub use core::iter::{FromIterator, Extend, IteratorExt};
    pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator};
    pub use core::iter::{ExactSizeIterator};
    pub use core::marker::{Copy, Send, Sized, Sync};
    pub use core::mem::drop;
    pub use core::ops::{Drop, Fn, FnMut, FnOnce};
    pub use core::option::Option;
    pub use core::option::Option::{Some, None};
    pub use core::ptr::PtrExt;
    pub use core::result::Result;
    pub use core::result::Result::{Ok, Err};

    // in core and collections (may differ).
    pub use slice::{AsSlice, SliceExt};
    pub use str::{Str, StrExt};

    // from other crates.
    pub use alloc::boxed::Box;
    pub use unicode::char::CharExt;

    // from collections.
    pub use borrow::IntoCow;
    pub use slice::SliceConcatExt;
    pub use string::{String, ToString};
    pub use vec::Vec;
}

/// An endpoint of a range of keys.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Bound<T> {
    /// An inclusive bound.
    Included(T),
    /// An exclusive bound.
    Excluded(T),
    /// An infinite endpoint. Indicates that there is no bound in this direction.
    Unbounded,
}
<|endoftext|>


<commit_before>use std::fs;
use std::io;

fn main() {
    std::process::exit(real_main());
}

fn real_main() -> i32 {
    let args: Vec<_> = std::env::args().collect();
    if args.len() < 2 {
        println!("Usage: {} <filename>", args[0]);
        return 1;
    }
    let fname = std::path::Path::new(&*args[1]);
    let file = fs::File::open(&fname).unwrap();

    let mut archive = zip::ZipArchive::new(file).unwrap();

    for i in 0..archive.len() {
        let mut file = archive.by_index(i).unwrap();
        let outpath = match file.name_as_child() {
            Some(path) => path,
            None => continue,
        };

        {
            let comment = file.comment();
            if !comment.is_empty() {
                println!("File {} comment: {}", i, comment);
            }
        }

        if (&*file.name()).ends_with('/') {
            println!("File {} extracted to \"{}\"", i, outpath.display());
            fs::create_dir_all(&outpath).unwrap();
        } else {
            println!(
                "File {} extracted to \"{}\" ({} bytes)",
                i,
                outpath.display(),
                file.size()
            );
            if let Some(p) = outpath.parent() {
                if !p.exists() {
                    fs::create_dir_all(&p).unwrap();
                }
            }
            let mut outfile = fs::File::create(&outpath).unwrap();
            io::copy(&mut file, &mut outfile).unwrap();
        }

        // Get and Set permissions
        #[cfg(unix)]
        {
            use std::os::unix::fs::PermissionsExt;

            if let Some(mode) = file.unix_mode() {
                fs::set_permissions(&outpath, fs::Permissions::from_mode(mode)).unwrap();
            }
        }
    }
    return 0;
}
<commit_msg>fix: overlapping borrows on unix platforms<commit_after>use std::fs;
use std::io;

fn main() {
    std::process::exit(real_main());
}

fn real_main() -> i32 {
    let args: Vec<_> = std::env::args().collect();
    if args.len() < 2 {
        println!("Usage: {} <filename>", args[0]);
        return 1;
    }
    let fname = std::path::Path::new(&*args[1]);
    let file = fs::File::open(&fname).unwrap();

    let mut archive = zip::ZipArchive::new(file).unwrap();

    for i in 0..archive.len() {
        let mut file = archive.by_index(i).unwrap();
        let outpath = match file.name_as_child() {
            Some(path) => path.to_owned(),
            None => continue,
        };

        {
            let comment = file.comment();
            if !comment.is_empty() {
                println!("File {} comment: {}", i, comment);
            }
        }

        if (&*file.name()).ends_with('/') {
            println!("File {} extracted to \"{}\"", i, outpath.display());
            fs::create_dir_all(&outpath).unwrap();
        } else {
            println!(
                "File {} extracted to \"{}\" ({} bytes)",
                i,
                outpath.display(),
                file.size()
            );
            if let Some(p) = outpath.parent() {
                if !p.exists() {
                    fs::create_dir_all(&p).unwrap();
                }
            }
            let mut outfile = fs::File::create(&outpath).unwrap();
            io::copy(&mut file, &mut outfile).unwrap();
        }

        // Get and Set permissions
        #[cfg(unix)]
        {
            use std::os::unix::fs::PermissionsExt;

            if let Some(mode) = file.unix_mode() {
                fs::set_permissions(&outpath, fs::Permissions::from_mode(mode)).unwrap();
            }
        }
    }
    return 0;
}
<|endoftext|>


<commit_before>extern crate num;

// the AdditiveIterator trait adds the sum() method to iterators
use std::iter::{AdditiveIterator,count};
// the Integer trait adds the is_odd() method to integer primitives
use num::Integer;

fn main() {
    println!("Find the sum of all the squared odd numbers under 1000");
    let upper: int = 1000;

    // imperative approach
    // declare accumulator variable
    let mut acc = 0;
    // iterate 0, 1, 2, ... to infinity
    for n in count(0, 1) {
        // square the number
        let n_squared = n * n;

        if n_squared >= upper {
            // break loop if exceeded the upper limit
            break;
        } else if n_squared.is_odd() {
            // accumulate value, if it's odd
            acc += n_squared;
        }
    }
    println!("imperative style: {}", acc);

    // functional approach
    let sum_of_squared_odd_numbers =
        // all natural numbers
        count(0, 1).
        // squared
        map(|n| n * n).
        // below upper limit
        take_while(|&n| n < upper).
        // that are odd
        filter(|n| n.is_odd()).
        // sum them
        sum();
    println!("functional style: {}", sum_of_squared_odd_numbers);
}
<commit_msg>hof: fix style<commit_after>extern crate num;

// The `AdditiveIterator` trait adds the `sum` method to iterators
use std::iter::{AdditiveIterator,count};
// The `Integer` trait adds the `is_odd` method to integer primitives
use num::Integer;

fn main() {
    println!("Find the sum of all the squared odd numbers under 1000");
    let upper: int = 1000;

    // Imperative approach
    // Declare accumulator variable
    let mut acc = 0;
    // Iterate: 0, 1, 2, ... to infinity
    for n in count(0, 1) {
        // Square the number
        let n_squared = n * n;

        if n_squared >= upper {
            // Break loop if exceeded the upper limit
            break;
        } else if n_squared.is_odd() {
            // Accumulate value, if it's odd
            acc += n_squared;
        }
    }
    println!("imperative style: {}", acc);

    // Functional approach
    let sum_of_squared_odd_numbers =
        // All natural numbers
        count(0, 1).
        // Squared
        map(|n| n * n).
        // Below upper limit
        take_while(|&n| n < upper).
        // That are odd
        filter(|n| n.is_odd()).
        // Sum them
        sum();
    println!("functional style: {}", sum_of_squared_odd_numbers);
}
<|endoftext|>


<commit_before>#[macro_use] extern crate log;
#[macro_use] extern crate itertools;
#[cfg(unix)] extern crate xdg_basedir;

extern crate clap;
extern crate config;

extern crate libimagstore;
extern crate libimagutil;

mod configuration;
mod logger;
mod runtime;

<commit_msg>rt: Make runtime module public<commit_after>#[macro_use] extern crate log;
#[macro_use] extern crate itertools;
#[cfg(unix)] extern crate xdg_basedir;

extern crate clap;
extern crate config;

extern crate libimagstore;
extern crate libimagutil;

mod configuration;
mod logger;

pub mod runtime;

<|endoftext|>


<commit_before>//! An example of using syntect for testing syntax definitions.
//! Basically exactly the same as what Sublime Text can do,
//! but without needing ST installed
extern crate syntect;
extern crate walkdir;
#[macro_use]
extern crate lazy_static;
extern crate regex;
//extern crate onig;
use syntect::parsing::{SyntaxSet, ParseState, ScopeStack, Scope};
use syntect::highlighting::ScopeSelectors;
use syntect::easy::{ScopeRegionIterator};

use std::path::Path;
use std::io::{BufRead, BufReader};
use std::fs::File;
use std::cmp::{min, max};
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use std::str::FromStr;
use regex::Regex;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestHeaderError {
    MalformedHeader,
    SyntaxDefinitionNotFound,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestFileResult {
    FailedAssertions(usize, usize),
    Success(usize),
}

lazy_static! {
    pub static ref SYNTAX_TEST_HEADER_PATTERN: Regex = Regex::new(r#"(?xm)
            ^(?P<testtoken_start>\s*\S+)
            \s+SYNTAX\sTEST\s+
            "(?P<syntax_file>[^"]+)"
            \s*(?P<testtoken_end>\S+)?$
        "#).unwrap();
    pub static ref SYNTAX_TEST_ASSERTION_PATTERN: Regex = Regex::new(r#"(?xm)
        \s*(?:
            (?P<begin_of_token><-)|(?P<range>\^+)
        )(.*)$"#).unwrap();
}

#[derive(Debug)]
struct AssertionRange<'a> {
    begin_char: usize,
    end_char: usize,
    scope_selector_text: &'a str,
    is_pure_assertion_line: bool,
}

#[derive(Debug)]
struct ScopedText {
    scope: Vec<Scope>,
    char_start: usize,
    text_len: usize,
}

#[derive(Debug)]
struct RangeTestResult {
    column_begin: usize,
    column_end: usize,
    success: bool,
}

fn get_line_assertion_details<'a>(testtoken_start: &str, testtoken_end: Option<&str>, line: &'a str) -> Option<AssertionRange<'a>> {
    // if the test start token specified in the test file's header is on the line
    if let Some(index) = line.find(testtoken_start) {
        let (before_token_start, token_and_rest_of_line) = line.split_at(index);

        if let Some(captures) = SYNTAX_TEST_ASSERTION_PATTERN.captures(&token_and_rest_of_line[testtoken_start.len()..]) {
            let mut sst = captures.get(3).unwrap().as_str(); // get the scope selector text
            let mut only_whitespace_after_token_end = true;

            if let Some(token) = testtoken_end { // if there is an end token defined in the test file header
                if let Some(end_token_pos) = sst.find(token) { // and there is an end token in the line
                    let (ss, after_token_end) = sst.split_at(end_token_pos); // the scope selector text ends at the end token
                    sst = &ss;
                    only_whitespace_after_token_end = after_token_end.trim_right().is_empty();
                }
            }
            return Some(AssertionRange {
                begin_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().start() } else { 0 },
                end_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().end() } else { 1 },
                scope_selector_text: sst,
                is_pure_assertion_line: before_token_start.trim_left().is_empty() && only_whitespace_after_token_end, // if only whitespace surrounds the test tokens on the line, then it is a pure assertion line
            });
        }
    }
    None
}

fn process_assertions(assertion: &AssertionRange, test_against_line_scopes: &Vec<ScopedText>) -> Vec<RangeTestResult> {
    // format the scope selector to include a space at the beginning, because, currently, ScopeSelector expects excludes to begin with " -"
    // and they are sometimes in the syntax test as ^^^-comment, for example
    let selector = ScopeSelectors::from_str(&format!(" {}", &assertion.scope_selector_text)).unwrap();
    // find the scope at the specified start column, and start matching the selector through the rest of the tokens on the line from there until the end column is reached
    let mut results = Vec::new();
    for scoped_text in test_against_line_scopes.iter().skip_while(|s|s.char_start + s.text_len <= assertion.begin_char).take_while(|s|s.char_start < assertion.end_char) {
        let match_value = selector.does_match(scoped_text.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(scoped_text.char_start, assertion.begin_char),
            column_end: min(scoped_text.char_start + scoped_text.text_len, assertion.end_char),
            success: match_value.is_some()
        };
        results.push(result);
    }
    // don't ignore assertions after the newline, they should be treated as though they are asserting against the newline
    let last = test_against_line_scopes.last().unwrap();
    if last.char_start + last.text_len < assertion.end_char {
        let match_value = selector.does_match(last.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(last.char_start + last.text_len, assertion.begin_char),
            column_end: assertion.end_char,
            success: match_value.is_some()
        };
        results.push(result);
    }
    results
}

/// If `parse_test_lines` is `false` then lines that only contain assertions are not parsed
fn test_file(ss: &SyntaxSet, path: &Path, parse_test_lines: bool) -> Result<SyntaxTestFileResult, SyntaxTestHeaderError> {
    let f = File::open(path).unwrap();
    let mut reader = BufReader::new(f);
    let mut line = String::new();

    // read the first line from the file - if we have reached EOF already, it's an invalid file
    if reader.read_line(&mut line).unwrap() == 0 {
        return Err(SyntaxTestHeaderError::MalformedHeader);
    }

    line = line.replace("\r", &"");

    // parse the syntax test header in the first line of the file
    let header_line = line.clone();
    let search_result = SYNTAX_TEST_HEADER_PATTERN.captures(&header_line);
    let captures = try!(search_result.ok_or(SyntaxTestHeaderError::MalformedHeader));

    let testtoken_start = captures.name("testtoken_start").unwrap().as_str();
    let testtoken_end = captures.name("testtoken_end").map_or(None, |c|Some(c.as_str()));
    let syntax_file = captures.name("syntax_file").unwrap().as_str();

    // find the relevant syntax definition to parse the file with - case is important!
    println!("The test file references syntax definition file: {}", syntax_file);
    let syntax = try!(ss.find_syntax_by_path(syntax_file).ok_or(SyntaxTestHeaderError::SyntaxDefinitionNotFound));

    // iterate over the lines of the file, testing them
    let mut state = ParseState::new(syntax);
    let mut stack = ScopeStack::new();

    let mut current_line_number = 1;
    let mut test_against_line_number = 1;
    let mut scopes_on_line_being_tested = Vec::new();
    let mut previous_non_assertion_line = line.to_string();

    let mut assertion_failures: usize = 0;
    let mut total_assertions: usize = 0;

    loop { // over lines of file, starting with the header line
        let mut line_only_has_assertion = false;
        let mut line_has_assertion = false;
        if let Some(assertion) = get_line_assertion_details(testtoken_start, testtoken_end, &line) {
            let result = process_assertions(&assertion, &scopes_on_line_being_tested);
            total_assertions += &assertion.end_char - &assertion.begin_char;
            for failure in result.iter().filter(|r|!r.success) {
                let chars = &previous_non_assertion_line[failure.column_begin..failure.column_end];
                println!("  Assertion selector {:?} \
                    from line {:?} failed against line {:?}, column range {:?}-{:?} \
                    (with text {:?}) \
                    has scope {:?}",
                    assertion.scope_selector_text.trim(),
                    current_line_number, test_against_line_number, failure.column_begin, failure.column_end,
                    chars,
                    scopes_on_line_being_tested.iter().skip_while(|s|s.char_start + s.text_len <= failure.column_begin).next().unwrap_or(scopes_on_line_being_tested.last().unwrap()).scope
                );
                assertion_failures += failure.column_end - failure.column_begin;
            }
            line_only_has_assertion = assertion.is_pure_assertion_line;
            line_has_assertion = true;
        }
        if !line_only_has_assertion || parse_test_lines {
            if !line_has_assertion { // ST seems to ignore lines that have assertions when calculating which line the assertion tests against
                scopes_on_line_being_tested.clear();
                test_against_line_number = current_line_number;
                previous_non_assertion_line = line.to_string();
            }
            let ops = state.parse_line(&line);
            let mut col: usize = 0;
            for (s, op) in ScopeRegionIterator::new(&ops, &line) {
                stack.apply(op);
                if s.is_empty() { // in this case we don't care about blank tokens
                    continue;
                }
                if !line_has_assertion {
                    // if the line has no assertions on it, remember the scopes on the line so we can test against them later
                    let len = s.chars().count();
                    scopes_on_line_being_tested.push(
                        ScopedText {
                            char_start: col,
                            text_len: len,
                            scope: stack.as_slice().to_vec()
                        }
                    );
                    // TODO: warn when there are duplicate adjacent (non-meta?) scopes, as it is almost always undesired
                    col += len;
                }
            }
        }

        line.clear();
        current_line_number += 1;
        if reader.read_line(&mut line).unwrap() == 0 {
            break;
        }
        line = line.replace("\r", &"");
    }
    if assertion_failures > 0 {
        Ok(SyntaxTestFileResult::FailedAssertions(assertion_failures, total_assertions))
    } else {
        Ok(SyntaxTestFileResult::Success(total_assertions))
    }
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let tests_path = if args.len() < 2 {
        "."
    } else {
        &args[1]
    };
    let syntaxes_path = if args.len() == 3 {
        &args[2]
    } else {
        ""
    };

    // load the syntaxes from disk if told to
    // (as opposed to from the binary dumps)
    // this helps to ensure that a recompile isn't needed
    // when using this for syntax development
    let mut ss = if syntaxes_path.is_empty() {
        SyntaxSet::load_defaults_newlines() // note we load the version with newlines
    } else {
        SyntaxSet::new()
    };
    if !syntaxes_path.is_empty() {
        println!("loading syntax definitions from {}", syntaxes_path);
        ss.load_syntaxes(&syntaxes_path, true).unwrap(); // note that we load the version with newlines
        ss.link_syntaxes();
    }

    let exit_code = recursive_walk(&ss, &tests_path);
    println!("exiting with code {}", exit_code);
    std::process::exit(exit_code);

}

fn recursive_walk(ss: &SyntaxSet, path: &str) -> i32 {
    let mut exit_code: i32 = 0; // exit with code 0 by default, if all tests pass
    let walker = WalkDir::new(path).into_iter();
    for entry in walker.filter_entry(|e|e.file_type().is_dir() || is_a_syntax_test_file(e)) {
        let entry = entry.unwrap();
        if entry.file_type().is_file() {
            println!("Testing file {}", entry.path().display());
            let result = test_file(&ss, entry.path(), true);
            println!("{:?}", result);
            if exit_code != 2 { // leave exit code 2 if there was an error
                if let Err(_) = result { // set exit code 2 if there was an error
                    exit_code = 2;
                } else if let Ok(ok) = result {
                    if let SyntaxTestFileResult::FailedAssertions(_, _) = ok {
                        exit_code = 1; // otherwise, if there were failures, exit with code 1
                    }
                }
            }
        }
    }
    exit_code
}

fn is_a_syntax_test_file(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("syntax_test_"))
         .unwrap_or(false)
}
<commit_msg>Fix panic in syntest with failed assertion on line with multi-byte chars<commit_after>//! An example of using syntect for testing syntax definitions.
//! Basically exactly the same as what Sublime Text can do,
//! but without needing ST installed
extern crate syntect;
extern crate walkdir;
#[macro_use]
extern crate lazy_static;
extern crate regex;
//extern crate onig;
use syntect::parsing::{SyntaxSet, ParseState, ScopeStack, Scope};
use syntect::highlighting::ScopeSelectors;
use syntect::easy::{ScopeRegionIterator};

use std::path::Path;
use std::io::{BufRead, BufReader};
use std::fs::File;
use std::cmp::{min, max};
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use std::str::FromStr;
use regex::Regex;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestHeaderError {
    MalformedHeader,
    SyntaxDefinitionNotFound,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestFileResult {
    FailedAssertions(usize, usize),
    Success(usize),
}

lazy_static! {
    pub static ref SYNTAX_TEST_HEADER_PATTERN: Regex = Regex::new(r#"(?xm)
            ^(?P<testtoken_start>\s*\S+)
            \s+SYNTAX\sTEST\s+
            "(?P<syntax_file>[^"]+)"
            \s*(?P<testtoken_end>\S+)?$
        "#).unwrap();
    pub static ref SYNTAX_TEST_ASSERTION_PATTERN: Regex = Regex::new(r#"(?xm)
        \s*(?:
            (?P<begin_of_token><-)|(?P<range>\^+)
        )(.*)$"#).unwrap();
}

#[derive(Debug)]
struct AssertionRange<'a> {
    begin_char: usize,
    end_char: usize,
    scope_selector_text: &'a str,
    is_pure_assertion_line: bool,
}

#[derive(Debug)]
struct ScopedText {
    scope: Vec<Scope>,
    char_start: usize,
    text_len: usize,
}

#[derive(Debug)]
struct RangeTestResult {
    column_begin: usize,
    column_end: usize,
    success: bool,
}

fn get_line_assertion_details<'a>(testtoken_start: &str, testtoken_end: Option<&str>, line: &'a str) -> Option<AssertionRange<'a>> {
    // if the test start token specified in the test file's header is on the line
    if let Some(index) = line.find(testtoken_start) {
        let (before_token_start, token_and_rest_of_line) = line.split_at(index);

        if let Some(captures) = SYNTAX_TEST_ASSERTION_PATTERN.captures(&token_and_rest_of_line[testtoken_start.len()..]) {
            let mut sst = captures.get(3).unwrap().as_str(); // get the scope selector text
            let mut only_whitespace_after_token_end = true;

            if let Some(token) = testtoken_end { // if there is an end token defined in the test file header
                if let Some(end_token_pos) = sst.find(token) { // and there is an end token in the line
                    let (ss, after_token_end) = sst.split_at(end_token_pos); // the scope selector text ends at the end token
                    sst = &ss;
                    only_whitespace_after_token_end = after_token_end.trim_right().is_empty();
                }
            }
            return Some(AssertionRange {
                begin_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().start() } else { 0 },
                end_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().end() } else { 1 },
                scope_selector_text: sst,
                is_pure_assertion_line: before_token_start.trim_left().is_empty() && only_whitespace_after_token_end, // if only whitespace surrounds the test tokens on the line, then it is a pure assertion line
            });
        }
    }
    None
}

fn process_assertions(assertion: &AssertionRange, test_against_line_scopes: &Vec<ScopedText>) -> Vec<RangeTestResult> {
    // format the scope selector to include a space at the beginning, because, currently, ScopeSelector expects excludes to begin with " -"
    // and they are sometimes in the syntax test as ^^^-comment, for example
    let selector = ScopeSelectors::from_str(&format!(" {}", &assertion.scope_selector_text)).unwrap();
    // find the scope at the specified start column, and start matching the selector through the rest of the tokens on the line from there until the end column is reached
    let mut results = Vec::new();
    for scoped_text in test_against_line_scopes.iter().skip_while(|s|s.char_start + s.text_len <= assertion.begin_char).take_while(|s|s.char_start < assertion.end_char) {
        let match_value = selector.does_match(scoped_text.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(scoped_text.char_start, assertion.begin_char),
            column_end: min(scoped_text.char_start + scoped_text.text_len, assertion.end_char),
            success: match_value.is_some()
        };
        results.push(result);
    }
    // don't ignore assertions after the newline, they should be treated as though they are asserting against the newline
    let last = test_against_line_scopes.last().unwrap();
    if last.char_start + last.text_len < assertion.end_char {
        let match_value = selector.does_match(last.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(last.char_start + last.text_len, assertion.begin_char),
            column_end: assertion.end_char,
            success: match_value.is_some()
        };
        results.push(result);
    }
    results
}

/// If `parse_test_lines` is `false` then lines that only contain assertions are not parsed
fn test_file(ss: &SyntaxSet, path: &Path, parse_test_lines: bool) -> Result<SyntaxTestFileResult, SyntaxTestHeaderError> {
    let f = File::open(path).unwrap();
    let mut reader = BufReader::new(f);
    let mut line = String::new();

    // read the first line from the file - if we have reached EOF already, it's an invalid file
    if reader.read_line(&mut line).unwrap() == 0 {
        return Err(SyntaxTestHeaderError::MalformedHeader);
    }

    line = line.replace("\r", &"");

    // parse the syntax test header in the first line of the file
    let header_line = line.clone();
    let search_result = SYNTAX_TEST_HEADER_PATTERN.captures(&header_line);
    let captures = try!(search_result.ok_or(SyntaxTestHeaderError::MalformedHeader));

    let testtoken_start = captures.name("testtoken_start").unwrap().as_str();
    let testtoken_end = captures.name("testtoken_end").map_or(None, |c|Some(c.as_str()));
    let syntax_file = captures.name("syntax_file").unwrap().as_str();

    // find the relevant syntax definition to parse the file with - case is important!
    println!("The test file references syntax definition file: {}", syntax_file);
    let syntax = try!(ss.find_syntax_by_path(syntax_file).ok_or(SyntaxTestHeaderError::SyntaxDefinitionNotFound));

    // iterate over the lines of the file, testing them
    let mut state = ParseState::new(syntax);
    let mut stack = ScopeStack::new();

    let mut current_line_number = 1;
    let mut test_against_line_number = 1;
    let mut scopes_on_line_being_tested = Vec::new();
    let mut previous_non_assertion_line = line.to_string();

    let mut assertion_failures: usize = 0;
    let mut total_assertions: usize = 0;

    loop { // over lines of file, starting with the header line
        let mut line_only_has_assertion = false;
        let mut line_has_assertion = false;
        if let Some(assertion) = get_line_assertion_details(testtoken_start, testtoken_end, &line) {
            let result = process_assertions(&assertion, &scopes_on_line_being_tested);
            total_assertions += &assertion.end_char - &assertion.begin_char;
            for failure in result.iter().filter(|r|!r.success) {
                let length = failure.column_end - failure.column_begin;
                let text: String = previous_non_assertion_line.chars().skip(failure.column_begin).take(length).collect();
                println!("  Assertion selector {:?} \
                    from line {:?} failed against line {:?}, column range {:?}-{:?} \
                    (with text {:?}) \
                    has scope {:?}",
                    assertion.scope_selector_text.trim(),
                    current_line_number, test_against_line_number, failure.column_begin, failure.column_end,
                    text,
                    scopes_on_line_being_tested.iter().skip_while(|s|s.char_start + s.text_len <= failure.column_begin).next().unwrap_or(scopes_on_line_being_tested.last().unwrap()).scope
                );
                assertion_failures += failure.column_end - failure.column_begin;
            }
            line_only_has_assertion = assertion.is_pure_assertion_line;
            line_has_assertion = true;
        }
        if !line_only_has_assertion || parse_test_lines {
            if !line_has_assertion { // ST seems to ignore lines that have assertions when calculating which line the assertion tests against
                scopes_on_line_being_tested.clear();
                test_against_line_number = current_line_number;
                previous_non_assertion_line = line.to_string();
            }
            let ops = state.parse_line(&line);
            let mut col: usize = 0;
            for (s, op) in ScopeRegionIterator::new(&ops, &line) {
                stack.apply(op);
                if s.is_empty() { // in this case we don't care about blank tokens
                    continue;
                }
                if !line_has_assertion {
                    // if the line has no assertions on it, remember the scopes on the line so we can test against them later
                    let len = s.chars().count();
                    scopes_on_line_being_tested.push(
                        ScopedText {
                            char_start: col,
                            text_len: len,
                            scope: stack.as_slice().to_vec()
                        }
                    );
                    // TODO: warn when there are duplicate adjacent (non-meta?) scopes, as it is almost always undesired
                    col += len;
                }
            }
        }

        line.clear();
        current_line_number += 1;
        if reader.read_line(&mut line).unwrap() == 0 {
            break;
        }
        line = line.replace("\r", &"");
    }
    if assertion_failures > 0 {
        Ok(SyntaxTestFileResult::FailedAssertions(assertion_failures, total_assertions))
    } else {
        Ok(SyntaxTestFileResult::Success(total_assertions))
    }
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let tests_path = if args.len() < 2 {
        "."
    } else {
        &args[1]
    };
    let syntaxes_path = if args.len() == 3 {
        &args[2]
    } else {
        ""
    };

    // load the syntaxes from disk if told to
    // (as opposed to from the binary dumps)
    // this helps to ensure that a recompile isn't needed
    // when using this for syntax development
    let mut ss = if syntaxes_path.is_empty() {
        SyntaxSet::load_defaults_newlines() // note we load the version with newlines
    } else {
        SyntaxSet::new()
    };
    if !syntaxes_path.is_empty() {
        println!("loading syntax definitions from {}", syntaxes_path);
        ss.load_syntaxes(&syntaxes_path, true).unwrap(); // note that we load the version with newlines
        ss.link_syntaxes();
    }

    let exit_code = recursive_walk(&ss, &tests_path);
    println!("exiting with code {}", exit_code);
    std::process::exit(exit_code);

}

fn recursive_walk(ss: &SyntaxSet, path: &str) -> i32 {
    let mut exit_code: i32 = 0; // exit with code 0 by default, if all tests pass
    let walker = WalkDir::new(path).into_iter();
    for entry in walker.filter_entry(|e|e.file_type().is_dir() || is_a_syntax_test_file(e)) {
        let entry = entry.unwrap();
        if entry.file_type().is_file() {
            println!("Testing file {}", entry.path().display());
            let result = test_file(&ss, entry.path(), true);
            println!("{:?}", result);
            if exit_code != 2 { // leave exit code 2 if there was an error
                if let Err(_) = result { // set exit code 2 if there was an error
                    exit_code = 2;
                } else if let Ok(ok) = result {
                    if let SyntaxTestFileResult::FailedAssertions(_, _) = ok {
                        exit_code = 1; // otherwise, if there were failures, exit with code 1
                    }
                }
            }
        }
    }
    exit_code
}

fn is_a_syntax_test_file(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("syntax_test_"))
         .unwrap_or(false)
}
<|endoftext|>


<commit_before>// Copyright 2018 Google Inc.
//
// 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
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use code_block::CodeBlock;
use errors::{CompilationError, Error};
use json;
use regex::Regex;
use std;
use std::collections::HashSet;
use std::fs;
use std::path::PathBuf;
use EvalContext;

fn shared_object_name_from_crate_name(crate_name: &str) -> String {
    if cfg!(target_os = "macos") {
        format!("lib{}.dylib", crate_name)
    } else if cfg!(target_os = "windows") {
        format!("{}.dll", crate_name)
    } else {
        format!("lib{}.so", crate_name)
    }
}

pub(crate) struct Module {
    pub(crate) crate_name: String,
    pub(crate) crate_dir: PathBuf,
    pub(crate) user_fn_name: String,
    target_dir: PathBuf,
    pub(crate) so_path: PathBuf,
    rs_filename: PathBuf,
    manual_deps: Vec<String>,
}

impl Module {
    pub(crate) fn new(
        eval_context: &EvalContext,
        crate_name: &str,
        previous_module: Option<&Module>,
    ) -> Result<Module, Error> {
        let target_dir = eval_context.target_dir();
        let crate_dir = eval_context.tmpdir_path.join(&crate_name);
        let src_dir = crate_dir.join("src");
        fs::create_dir_all(&src_dir)?;
        let rs_filename = src_dir.join("lib.rs");
        let so_path = eval_context
            .deps_dir()
            .join(shared_object_name_from_crate_name(crate_name));

        let module = Module {
            so_path,
            crate_name: crate_name.to_owned(),
            user_fn_name: format!("run_{}", crate_name),
            crate_dir,
            target_dir,
            rs_filename,
            manual_deps: vec![],
        };
        if let Some(previous_module) = previous_module {
            // Copy the lock file from our previous compilation, if any, to
            // avoid having Cargo recreate it, which would be time consuming
            // (more than a second on my machine).
            fs::copy(previous_module.cargo_lock_path(), &module.cargo_lock_path())?;
        }
        Ok(module)
    }

    fn cargo_lock_path(&self) -> PathBuf {
        self.crate_dir.join("Cargo.lock")
    }

    pub(crate) fn write_sources_and_compile(
        &mut self,
        eval_context: &EvalContext,
        code_block: &CodeBlock,
    ) -> Result<(), Error> {
        self.write_cargo_toml(eval_context)?;
        self.compile(code_block)
    }

    // Writes Cargo.toml. Should be called before compile (or just use
    // write_sources_and_compile).
    pub(crate) fn write_cargo_toml(&mut self, eval_context: &EvalContext) -> Result<(), Error> {
        fs::write(
            self.crate_dir.join("Cargo.toml"),
            self.get_cargo_toml_contents(eval_context),
        )?;
        Ok(())
    }

    pub(crate) fn add_dep(&mut self, module: &Module) {
        self.manual_deps.push(module.crate_name.clone());
    }

    pub(crate) fn compile(&mut self, code_block: &CodeBlock) -> Result<(), Error> {
        fs::write(self.rs_filename.clone(), code_block.to_string().as_bytes())?;

        // Our compiler errors should all be in JSON format, but for errors from Cargo errors, we
        // need to add explicit matching for those errors that we expect we might see.
        lazy_static! {
            static ref KNOWN_NON_JSON_ERRORS: Regex =
                Regex::new("(error: no matching package named)").unwrap();
        }

        let mut command = std::process::Command::new("cargo");
        command
            .env("CARGO_TARGET_DIR", &self.target_dir)
            .arg("rustc")
            .arg("--")
            .arg("-C")
            .arg("prefer-dynamic")
            .arg("--error-format")
            .arg("json")
            .current_dir(&self.crate_dir);
        let cargo_output = command.output()?;
        if !cargo_output.status.success() {
            let stderr = String::from_utf8_lossy(&cargo_output.stderr);
            let stdout = String::from_utf8_lossy(&cargo_output.stdout);
            let mut non_json_error = None;
            let errors: Vec<CompilationError> = stderr
                .lines().chain(stdout.lines())
                .filter_map(|line| {
                    json::parse(&line)
                        .ok()
                        .and_then(|json| CompilationError::opt_new(json, code_block))
                        .or_else(|| {
                            if KNOWN_NON_JSON_ERRORS.is_match(line) {
                                non_json_error = Some(line);
                            }
                            None
                        })
                })
                .collect();
            if errors.is_empty() {
                if let Some(error) = non_json_error {
                    bail!(Error::JustMessage(error.to_owned()));
                } else {
                    bail!(Error::JustMessage(format!(
                        "Compilation failed, but no parsable errors were found. STDERR:\n\
                         {}\nSTDOUT:{}\n",
                        stderr,
                        stdout
                    )));
                }
            } else {
                bail!(Error::CompilationErrors(errors));
            }
        }
        Ok(())
    }

    fn get_cargo_toml_contents(&self, eval_context: &EvalContext) -> String {
        use std::fmt::Write;
        let mut loaded_module_deps = String::new();
        let combined_deps = eval_context
            .modules_iter()
            .map(|m| &m.crate_name)
            .chain(self.manual_deps.iter())
            .collect::<HashSet<_>>();
        for crate_name in combined_deps {
            writeln!(
                &mut loaded_module_deps,
                "{} = {{ path = \"../{}\" }}",
                crate_name, crate_name
            )
            .unwrap();
        }
        let crate_imports = eval_context.format_cargo_deps();
        format!(
            r#"
[package]
name = "{}"
version = "1.0.0"

[lib]
crate-type = ["dylib"]

[profile.dev]
opt-level = {}
debug = true
rpath = true
lto = false
debug-assertions = true
codegen-units = 16
panic = 'unwind'
incremental = true
overflow-checks = true

[dependencies]
{}
{}
"#,
            self.crate_name,
            eval_context.opt_level(),
            loaded_module_deps,
            crate_imports
        )
    }
}
<commit_msg>Change the flag used to request errors a JSON as passing --error-format=json via cargo rustc no longer works with recent nightly versions of cargo<commit_after>// Copyright 2018 Google Inc.
//
// 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
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use code_block::CodeBlock;
use errors::{CompilationError, Error};
use json;
use regex::Regex;
use std;
use std::collections::HashSet;
use std::fs;
use std::path::PathBuf;
use EvalContext;

fn shared_object_name_from_crate_name(crate_name: &str) -> String {
    if cfg!(target_os = "macos") {
        format!("lib{}.dylib", crate_name)
    } else if cfg!(target_os = "windows") {
        format!("{}.dll", crate_name)
    } else {
        format!("lib{}.so", crate_name)
    }
}

pub(crate) struct Module {
    pub(crate) crate_name: String,
    pub(crate) crate_dir: PathBuf,
    pub(crate) user_fn_name: String,
    target_dir: PathBuf,
    pub(crate) so_path: PathBuf,
    rs_filename: PathBuf,
    manual_deps: Vec<String>,
}

impl Module {
    pub(crate) fn new(
        eval_context: &EvalContext,
        crate_name: &str,
        previous_module: Option<&Module>,
    ) -> Result<Module, Error> {
        let target_dir = eval_context.target_dir();
        let crate_dir = eval_context.tmpdir_path.join(&crate_name);
        let src_dir = crate_dir.join("src");
        fs::create_dir_all(&src_dir)?;
        let rs_filename = src_dir.join("lib.rs");
        let so_path = eval_context
            .deps_dir()
            .join(shared_object_name_from_crate_name(crate_name));

        let module = Module {
            so_path,
            crate_name: crate_name.to_owned(),
            user_fn_name: format!("run_{}", crate_name),
            crate_dir,
            target_dir,
            rs_filename,
            manual_deps: vec![],
        };
        if let Some(previous_module) = previous_module {
            // Copy the lock file from our previous compilation, if any, to
            // avoid having Cargo recreate it, which would be time consuming
            // (more than a second on my machine).
            fs::copy(previous_module.cargo_lock_path(), &module.cargo_lock_path())?;
        }
        Ok(module)
    }

    fn cargo_lock_path(&self) -> PathBuf {
        self.crate_dir.join("Cargo.lock")
    }

    pub(crate) fn write_sources_and_compile(
        &mut self,
        eval_context: &EvalContext,
        code_block: &CodeBlock,
    ) -> Result<(), Error> {
        self.write_cargo_toml(eval_context)?;
        self.compile(code_block)
    }

    // Writes Cargo.toml. Should be called before compile (or just use
    // write_sources_and_compile).
    pub(crate) fn write_cargo_toml(&mut self, eval_context: &EvalContext) -> Result<(), Error> {
        fs::write(
            self.crate_dir.join("Cargo.toml"),
            self.get_cargo_toml_contents(eval_context),
        )?;
        Ok(())
    }

    pub(crate) fn add_dep(&mut self, module: &Module) {
        self.manual_deps.push(module.crate_name.clone());
    }

    pub(crate) fn compile(&mut self, code_block: &CodeBlock) -> Result<(), Error> {
        fs::write(self.rs_filename.clone(), code_block.to_string().as_bytes())?;

        // Our compiler errors should all be in JSON format, but for errors from Cargo errors, we
        // need to add explicit matching for those errors that we expect we might see.
        lazy_static! {
            static ref KNOWN_NON_JSON_ERRORS: Regex =
                Regex::new("(error: no matching package named)").unwrap();
        }

        let mut command = std::process::Command::new("cargo");
        command
            .env("CARGO_TARGET_DIR", &self.target_dir)
            .arg("rustc")
            .arg("--message-format=json")
            .arg("--")
            .arg("-C")
            .arg("prefer-dynamic")
            .current_dir(&self.crate_dir);
        let cargo_output = command.output()?;
        if !cargo_output.status.success() {
            let stderr = String::from_utf8_lossy(&cargo_output.stderr);
            let stdout = String::from_utf8_lossy(&cargo_output.stdout);
            let mut non_json_error = None;
            let errors: Vec<CompilationError> = stderr
                .lines().chain(stdout.lines())
                .filter_map(|line| {
                    json::parse(&line)
                        .ok()
                        .and_then(|json| CompilationError::opt_new(json, code_block))
                        .or_else(|| {
                            if KNOWN_NON_JSON_ERRORS.is_match(line) {
                                non_json_error = Some(line);
                            }
                            None
                        })
                })
                .collect();
            if errors.is_empty() {
                if let Some(error) = non_json_error {
                    bail!(Error::JustMessage(error.to_owned()));
                } else {
                    bail!(Error::JustMessage(format!(
                        "Compilation failed, but no parsable errors were found. STDERR:\n\
                         {}\nSTDOUT:{}\n",
                        stderr,
                        stdout
                    )));
                }
            } else {
                bail!(Error::CompilationErrors(errors));
            }
        }
        Ok(())
    }

    fn get_cargo_toml_contents(&self, eval_context: &EvalContext) -> String {
        use std::fmt::Write;
        let mut loaded_module_deps = String::new();
        let combined_deps = eval_context
            .modules_iter()
            .map(|m| &m.crate_name)
            .chain(self.manual_deps.iter())
            .collect::<HashSet<_>>();
        for crate_name in combined_deps {
            writeln!(
                &mut loaded_module_deps,
                "{} = {{ path = \"../{}\" }}",
                crate_name, crate_name
            )
            .unwrap();
        }
        let crate_imports = eval_context.format_cargo_deps();
        format!(
            r#"
[package]
name = "{}"
version = "1.0.0"

[lib]
crate-type = ["dylib"]

[profile.dev]
opt-level = {}
debug = true
rpath = true
lto = false
debug-assertions = true
codegen-units = 16
panic = 'unwind'
incremental = true
overflow-checks = true

[dependencies]
{}
{}
"#,
            self.crate_name,
            eval_context.opt_level(),
            loaded_module_deps,
            crate_imports
        )
    }
}
<|endoftext|>


<commit_before>extern crate indicatif;
extern crate console;
extern crate rand;

use std::thread;
use std::time::{Instant, Duration};
use rand::Rng;

use indicatif::{ProgressBar, ProgressStyle, MultiProgress, HumanDuration};
use console::{Emoji, style};

static PACKAGES: &'static [&'static str] = &[
    "fs-events",
    "my-awesome-module",
    "emoji-speaker",
    "wrap-ansi",
    "stream-browserify",
    "acorn-dynamic-import",
];

static COMMANDS: &'static [&'static str] = &[
    "cmake .",
    "make",
    "make clean",
    "gcc foo.c -o foo",
    "gcc bar.c -o bar",
    "./helper.sh rebuild-cache",
    "make all-clean",
    "make test",
];

static LOOKING_GLASS: Emoji = Emoji("🔍  ", "");
static TRUCK: Emoji = Emoji("🚚  ", "");
static CLIP: Emoji = Emoji("🔗  ", "");
static PAPER: Emoji = Emoji("📃  ", "");
static SPARKLE: Emoji = Emoji("✨ ", ":-)");

pub fn main() {
    let mut rng = rand::thread_rng();
    let started = Instant::now();
    let spinner_style = ProgressStyle::default_spinner()
        .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ ")
        .template("{prefix:.bold.dim} {spinner} {wide_msg}");

    println!("{} {}Resolving packages...", style("[1/4]").bold().dim(), LOOKING_GLASS);
    println!("{} {}Fetching packages...", style("[2/4]").bold().dim(), TRUCK);

    println!("{} {}Linking dependencies...", style("[3/4]").bold().dim(), CLIP);
    let deps = 1232;
    let pb = ProgressBar::new(deps);
    for _ in 0..deps {
        pb.inc(1);
        thread::sleep(Duration::from_millis(3));
    }
    pb.finish_and_clear();

    println!("{} {}Building fresh packages...", style("[4/4]").bold().dim(), PAPER);
    let m = MultiProgress::new();
    for i in 0..4 {
        let count = rng.gen_range(30, 80);
        let pb = m.add(ProgressBar::new(count));
        pb.set_style(spinner_style.clone());
        pb.set_prefix(&format!("[{}/?]", i + 1));
        let _ = thread::spawn(move || {
            let mut rng = rand::thread_rng();
            let pkg = rng.choose(PACKAGES).unwrap();
            for _ in 0..count {
                let cmd = rng.choose(COMMANDS).unwrap();
                pb.set_message(&format!("{}: {}", pkg, cmd));
                pb.inc(1);
                thread::sleep(Duration::from_millis(rng.gen_range(25, 200)));
            }
            pb.finish_with_message("waiting...");
        });
    }
    m.join_and_clear().unwrap();

    println!("{} Done in {}", HumanDuration(started.elapsed()), SPARKLE);
}
<commit_msg>Fixed last line of yarnish example (#31)<commit_after>extern crate indicatif;
extern crate console;
extern crate rand;

use std::thread;
use std::time::{Instant, Duration};
use rand::Rng;

use indicatif::{ProgressBar, ProgressStyle, MultiProgress, HumanDuration};
use console::{Emoji, style};

static PACKAGES: &'static [&'static str] = &[
    "fs-events",
    "my-awesome-module",
    "emoji-speaker",
    "wrap-ansi",
    "stream-browserify",
    "acorn-dynamic-import",
];

static COMMANDS: &'static [&'static str] = &[
    "cmake .",
    "make",
    "make clean",
    "gcc foo.c -o foo",
    "gcc bar.c -o bar",
    "./helper.sh rebuild-cache",
    "make all-clean",
    "make test",
];

static LOOKING_GLASS: Emoji = Emoji("🔍  ", "");
static TRUCK: Emoji = Emoji("🚚  ", "");
static CLIP: Emoji = Emoji("🔗  ", "");
static PAPER: Emoji = Emoji("📃  ", "");
static SPARKLE: Emoji = Emoji("✨ ", ":-)");

pub fn main() {
    let mut rng = rand::thread_rng();
    let started = Instant::now();
    let spinner_style = ProgressStyle::default_spinner()
        .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ ")
        .template("{prefix:.bold.dim} {spinner} {wide_msg}");

    println!("{} {}Resolving packages...", style("[1/4]").bold().dim(), LOOKING_GLASS);
    println!("{} {}Fetching packages...", style("[2/4]").bold().dim(), TRUCK);

    println!("{} {}Linking dependencies...", style("[3/4]").bold().dim(), CLIP);
    let deps = 1232;
    let pb = ProgressBar::new(deps);
    for _ in 0..deps {
        pb.inc(1);
        thread::sleep(Duration::from_millis(3));
    }
    pb.finish_and_clear();

    println!("{} {}Building fresh packages...", style("[4/4]").bold().dim(), PAPER);
    let m = MultiProgress::new();
    for i in 0..4 {
        let count = rng.gen_range(30, 80);
        let pb = m.add(ProgressBar::new(count));
        pb.set_style(spinner_style.clone());
        pb.set_prefix(&format!("[{}/?]", i + 1));
        let _ = thread::spawn(move || {
            let mut rng = rand::thread_rng();
            let pkg = rng.choose(PACKAGES).unwrap();
            for _ in 0..count {
                let cmd = rng.choose(COMMANDS).unwrap();
                pb.set_message(&format!("{}: {}", pkg, cmd));
                pb.inc(1);
                thread::sleep(Duration::from_millis(rng.gen_range(25, 200)));
            }
            pb.finish_with_message("waiting...");
        });
    }
    m.join_and_clear().unwrap();

    println!("{} Done in {}", SPARKLE, HumanDuration(started.elapsed()));
}
<|endoftext|>


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

extern crate glutin_window;
extern crate graphics;
extern crate rebind;
extern crate piston;
extern crate opengl_graphics;
extern crate viewport;

use glutin_window::GlutinWindow;
use graphics::*;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventMap, Events};
use piston::input::{
    Event,
    Input,
    Motion,
    RenderArgs,
    RenderEvent,
    UpdateArgs,
    UpdateEvent
};
use piston::input::keyboard::Key;
use piston::input::Button::Keyboard;
use piston::window::WindowSettings;
use rebind::{Action, InputTranslator, RebindBuilder, Translated};
use std::cell::RefCell;
use std::rc::Rc;

struct App {
    window: Rc<RefCell<GlutinWindow>>,
    graphics: Rc<RefCell<GlGraphics>>,
    translator: InputTranslator<CharacterAction>,
    character: Character,
    cursor_pos: [f64; 2],
    bg_color: [f32; 4]
}

impl App {
    fn input(&mut self, input: &Input) {
        if let Some(t) = self.translator.translate(input) {
            match t {
                Translated::Press(action) => {
                    match action {
                        CharacterAction::Jump => {

                        },
                        CharacterAction::MoveLeft => {
                            self.character.current_velocity[0] += 0.5
                        },
                        CharacterAction::MoveRight => {
                            self.character.current_velocity[0] -= 0.5
                        }
                    }
                },
                Translated::Release(_) => {
                    self.character.current_velocity = [0.0, 0.0];
                },
                Translated::Move(Motion::MouseCursor(x, y)) => {
                    self.cursor_pos = [x, y];
                }
                _ => { }
            }
        }
    }

    fn update(&mut self, args: &UpdateArgs) {

    }

    fn render(&mut self, args: &RenderArgs) {
        let mut gl_graphics = self.graphics.borrow_mut();

        // draw the background color
        {
            gl_graphics.draw(args.viewport(), |_, gl| clear(self.bg_color, gl));
        }

        // draw the character
        {
            let square = rectangle::square(self.character.topleft[0], self.character.topleft[1], self.character.size);
            let (x, y) = ((args.width / 2) as f64, (args.height / 2) as f64);

            gl_graphics.draw(args.viewport(), |c, gl| {
                let transform = c.transform.trans(x, y);
                rectangle(self.character.color, square, transform, gl);
            });
        }

        // draw the cursor dot
        {
            let dot = ellipse::circle(self.cursor_pos[0], self.cursor_pos[1], 5.0);
            gl_graphics.draw(args.viewport(), |c, gl| ellipse([0.0, 1.0, 0.0, 1.0], dot, c.transform, gl));
        }
    }
}

struct Character {
    color: [f32; 4],
    topleft: [f64; 2],
    current_velocity: [f64; 2],
    size: f64
}

impl Character {
    fn new(col: [f32; 4], tl: [f64; 2], sz: f64) -> Self {
        Character {
            color: col,
            topleft: tl,
            current_velocity: [0.0f64, 0.0],
            size: sz
        }
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
enum CharacterAction {
    Jump,
    MoveLeft,
    MoveRight
}

impl Action for CharacterAction { }

fn main() {
    const WINDOW_SIZE: (u32, u32)  = (800, 600);
    const OPENGL: OpenGL = OpenGL::V3_2;

    let window = WindowSettings::new("calaxite", WINDOW_SIZE)
        .exit_on_esc(true)
        .fullscreen(false)
        .opengl(OPENGL)
        .vsync(true)
        .build()
        .unwrap_or_else(|e| panic!("Could not create window: {}", e));

    let gl_graphics = GlGraphics::new(OPENGL);

    let translator = RebindBuilder::new(WINDOW_SIZE.into())
        .with_action_mapping(Keyboard(Key::Space), CharacterAction::Jump)
        .with_action_mapping(Keyboard(Key::Left),  CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::A),     CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::Right), CharacterAction::MoveRight)
        .with_action_mapping(Keyboard(Key::D),     CharacterAction::MoveRight)
        .build_translator();

    let character = Character::new([1.0, 0.0, 0.0, 1.0],
                                   [30.0, 30.0],
                                   50.0);

    let mut app = App {
        window: Rc::new(RefCell::new(window)),
        graphics: Rc::new(RefCell::new(gl_graphics)),
        translator: translator,
        character: character,
        cursor_pos: [0.0, 0.0],
        bg_color: [0.0, 0.0, 0.0, 1.0] // black background
    };

    for e in app.window.clone().events() {
        match e {
            Event::Render(r) => { app.render(&r); },
            Event::Update(u) => { app.update(&u); },
            Event::Input(i)  => { app.input(&i); },
            _ => { }
        }
    }
}
<commit_msg>More semicolons added<commit_after>#![allow(dead_code, unused_variables)]

extern crate glutin_window;
extern crate graphics;
extern crate rebind;
extern crate piston;
extern crate opengl_graphics;
extern crate viewport;

use glutin_window::GlutinWindow;
use graphics::*;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventMap, Events};
use piston::input::{
    Event,
    Input,
    Motion,
    RenderArgs,
    RenderEvent,
    UpdateArgs,
    UpdateEvent
};
use piston::input::keyboard::Key;
use piston::input::Button::Keyboard;
use piston::window::WindowSettings;
use rebind::{Action, InputTranslator, RebindBuilder, Translated};
use std::cell::RefCell;
use std::rc::Rc;

struct App {
    window: Rc<RefCell<GlutinWindow>>,
    graphics: Rc<RefCell<GlGraphics>>,
    translator: InputTranslator<CharacterAction>,
    character: Character,
    cursor_pos: [f64; 2],
    bg_color: [f32; 4]
}

impl App {
    fn input(&mut self, input: &Input) {
        if let Some(t) = self.translator.translate(input) {
            match t {
                Translated::Press(action) => {
                    match action {
                        CharacterAction::Jump => {

                        },
                        CharacterAction::MoveLeft => {
                            self.character.current_velocity[0] += 0.5;
                        },
                        CharacterAction::MoveRight => {
                            self.character.current_velocity[0] -= 0.5;
                        }
                    }
                },
                Translated::Release(_) => {
                    self.character.current_velocity = [0.0, 0.0];
                },
                Translated::Move(Motion::MouseCursor(x, y)) => {
                    self.cursor_pos = [x, y];
                }
                _ => { }
            }
        }
    }

    fn update(&mut self, args: &UpdateArgs) {

    }

    fn render(&mut self, args: &RenderArgs) {
        let mut gl_graphics = self.graphics.borrow_mut();

        // draw the background color
        {
            gl_graphics.draw(args.viewport(), |_, gl| clear(self.bg_color, gl));
        }

        // draw the character
        {
            let square = rectangle::square(self.character.topleft[0], self.character.topleft[1], self.character.size);
            let (x, y) = ((args.width / 2) as f64, (args.height / 2) as f64);

            gl_graphics.draw(args.viewport(), |c, gl| {
                let transform = c.transform.trans(x, y);
                rectangle(self.character.color, square, transform, gl);
            });
        }

        // draw the cursor dot
        {
            let dot = ellipse::circle(self.cursor_pos[0], self.cursor_pos[1], 5.0);
            gl_graphics.draw(args.viewport(), |c, gl| ellipse([0.0, 1.0, 0.0, 1.0], dot, c.transform, gl));
        }
    }
}

struct Character {
    color: [f32; 4],
    topleft: [f64; 2],
    current_velocity: [f64; 2],
    size: f64
}

impl Character {
    fn new(col: [f32; 4], tl: [f64; 2], sz: f64) -> Self {
        Character {
            color: col,
            topleft: tl,
            current_velocity: [0.0f64, 0.0],
            size: sz
        }
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
enum CharacterAction {
    Jump,
    MoveLeft,
    MoveRight
}

impl Action for CharacterAction { }

fn main() {
    const WINDOW_SIZE: (u32, u32)  = (800, 600);
    const OPENGL: OpenGL = OpenGL::V3_2;

    let window = WindowSettings::new("calaxite", WINDOW_SIZE)
        .exit_on_esc(true)
        .fullscreen(false)
        .opengl(OPENGL)
        .vsync(true)
        .build()
        .unwrap_or_else(|e| panic!("Could not create window: {}", e));

    let gl_graphics = GlGraphics::new(OPENGL);

    let translator = RebindBuilder::new(WINDOW_SIZE.into())
        .with_action_mapping(Keyboard(Key::Space), CharacterAction::Jump)
        .with_action_mapping(Keyboard(Key::Left),  CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::A),     CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::Right), CharacterAction::MoveRight)
        .with_action_mapping(Keyboard(Key::D),     CharacterAction::MoveRight)
        .build_translator();

    let character = Character::new([1.0, 0.0, 0.0, 1.0],
                                   [30.0, 30.0],
                                   50.0);

    let mut app = App {
        window: Rc::new(RefCell::new(window)),
        graphics: Rc::new(RefCell::new(gl_graphics)),
        translator: translator,
        character: character,
        cursor_pos: [0.0, 0.0],
        bg_color: [0.0, 0.0, 0.0, 1.0] // black background
    };

    for e in app.window.clone().events() {
        match e {
            Event::Render(r) => { app.render(&r); },
            Event::Update(u) => { app.update(&u); },
            Event::Input(i)  => { app.input(&i); },
            _ => { }
        }
    }
}
<|endoftext|>


<commit_before>extern crate piston_window;
extern crate vecmath;
extern crate camera_controllers;
#[macro_use]
extern crate gfx;
extern crate gfx_device_gl;
extern crate sdl2_window;
extern crate piston_meta;

use std::fs::File;
use std::io::Read;
use sdl2_window::Sdl2Window;
use piston_window::*;
use camera_controllers::{
    FirstPersonSettings,
    FirstPerson,
    CameraPerspective,
    model_view_projection
};
use gfx::traits::*;
use piston_meta::*;

//----------------------------------------
// Cube associated data

gfx_vertex!( Vertex {
    a_pos@ a_pos: [f32; 3],
    a_tex_coord@ a_tex_coord: [f32; 2],
});

impl Vertex {
    fn new(pos: [f32; 3], tc: [f32; 2]) -> Vertex {
        Vertex {
            a_pos: pos,
            a_tex_coord: tc,
        }
    }
}

gfx_parameters!( Params {
    u_model_view_proj@ u_model_view_proj: [[f32; 4]; 4],
    t_color@ t_color: gfx::shade::TextureParam<R>,
});

//----------------------------------------

fn main() {
    let mut events: PistonWindow<Sdl2Window> =
        WindowSettings::new("piston: cube", [640, 480])
        .exit_on_esc(true)
        .samples(4)
        .into();
    events.set_capture_cursor(true);

    let ref mut factory = events.factory.borrow().clone();

    // Read OpenGEX meta rules.
    let mut file_h = File::open("assets/opengex-syntax.txt").unwrap();
    let mut source = String::new();
    file_h.read_to_string(&mut source).unwrap();
    let rules = stderr_unwrap(&source, syntax(&source));

    // Read cube.ogex.
    let mut file_h = File::open("assets/cube.ogex").unwrap();
    let mut source = String::new();
    file_h.read_to_string(&mut source).unwrap();
    let data = stderr_unwrap(&source, parse(&rules, &source));

    let v3 = |mut s: &mut Search| Ok([
        try!(s.f64("x")) as f32,
        try!(s.f64("y")) as f32,
        try!(s.f64("z")) as f32
    ]);

    let s = Search::new(&data);
    let vertex_data: Vec<Vertex> = stderr_unwrap(&source, s.for_bool("position", true,
        |ref mut s| {
        Ok(vec![
            Vertex::new(try!(v3(s)), [0.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 1.0]),
            Vertex::new(try!(v3(s)), [0.0, 1.0]),
            //bottom (0, 0, -1)
            Vertex::new(try!(v3(s)), [0.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 1.0]),
            Vertex::new(try!(v3(s)), [0.0, 1.0]),
            //right (1, 0, 0)
            Vertex::new(try!(v3(s)), [0.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 1.0]),
            Vertex::new(try!(v3(s)), [0.0, 1.0]),
            //left (-1, 0, 0)
            Vertex::new(try!(v3(s)), [0.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 1.0]),
            Vertex::new(try!(v3(s)), [0.0, 1.0]),
            //front (0, 1, 0)
            Vertex::new(try!(v3(s)), [0.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 1.0]),
            Vertex::new(try!(v3(s)), [0.0, 1.0]),
            //back (0, -1, 0)
            Vertex::new(try!(v3(s)), [0.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 0.0]),
            Vertex::new(try!(v3(s)), [1.0, 1.0]),
            Vertex::new(try!(v3(s)), [0.0, 1.0]),
        ])
    }));

    let mesh = factory.create_mesh(&vertex_data);

    let index_data: &[u8] = &[
         0,  1,  2,  2,  3,  0, // top
         4,  6,  5,  6,  4,  7, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 14, 13, 14, 12, 16, // left
        16, 18, 17, 18, 16, 19, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = index_data.to_slice(factory, gfx::PrimitiveType::TriangleList);

    let texture = factory.create_texture_rgba8_static(1, 1, &[0x00_C0_A0_20]).unwrap();

    let sampler = factory.create_sampler(
        gfx::tex::SamplerInfo::new(gfx::tex::FilterMethod::Bilinear,
                                   gfx::tex::WrapMode::Clamp)
    );

    let program = {
        let vertex = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("../assets/cube_120.glslv")),
            glsl_150: Some(include_bytes!("../assets/cube_150.glslv")),
            .. gfx::ShaderSource::empty()
        };
        let fragment = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("../assets/cube_120.glslf")),
            glsl_150: Some(include_bytes!("../assets/cube_150.glslf")),
            .. gfx::ShaderSource::empty()
        };
        factory.link_program_source(vertex, fragment).unwrap()
    };

    let mut data = Params {
        u_model_view_proj: vecmath::mat4_id(),
        t_color: (texture, Some(sampler)),
        _r: std::marker::PhantomData,
    };

    let get_projection = |w: &PistonWindow<Sdl2Window>| {
        let draw_size = w.window.borrow().draw_size();
        CameraPerspective {
            fov: 90.0, near_clip: 0.1, far_clip: 1000.0,
            aspect_ratio: (draw_size.width as f32) / (draw_size.height as f32)
        }.projection()
    };

    let model = vecmath::mat4_id();
    let mut projection = get_projection(&events);
    let mut first_person = FirstPerson::new(
        [0.5, 0.5, 4.0],
        FirstPersonSettings::keyboard_wasd()
    );
    let state = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);

    for e in events {
        first_person.event(&e);

        e.draw_3d(|stream| {
            let args = e.render_args().unwrap();
            stream.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                }
            );
            data.u_model_view_proj = model_view_projection(
                model,
                first_person.camera(args.ext_dt).orthogonal(),
                projection
            );
            stream.draw(&(&mesh, slice.clone(), &program, &data, &state)).unwrap();
        });

        if let Some(_) = e.resize_args() {
            projection = get_projection(&e);
        }
    }
}
<commit_msg>Separate texture coordinates<commit_after>extern crate piston_window;
extern crate vecmath;
extern crate camera_controllers;
#[macro_use]
extern crate gfx;
extern crate gfx_device_gl;
extern crate sdl2_window;
extern crate piston_meta;

use std::fs::File;
use std::io::Read;
use sdl2_window::Sdl2Window;
use piston_window::*;
use camera_controllers::{
    FirstPersonSettings,
    FirstPerson,
    CameraPerspective,
    model_view_projection
};
use gfx::traits::*;
use piston_meta::*;

//----------------------------------------
// Cube associated data

gfx_vertex!( Vertex {
    a_pos@ a_pos: [f32; 3],
    a_tex_coord@ a_tex_coord: [f32; 2],
});

impl Vertex {
    fn new(pos: [f32; 3], tc: [f32; 2]) -> Vertex {
        Vertex {
            a_pos: pos,
            a_tex_coord: tc,
        }
    }
}

gfx_parameters!( Params {
    u_model_view_proj@ u_model_view_proj: [[f32; 4]; 4],
    t_color@ t_color: gfx::shade::TextureParam<R>,
});

//----------------------------------------

fn main() {
    let mut events: PistonWindow<Sdl2Window> =
        WindowSettings::new("piston: cube", [640, 480])
        .exit_on_esc(true)
        .samples(4)
        .into();
    events.set_capture_cursor(true);

    let ref mut factory = events.factory.borrow().clone();

    // Read OpenGEX meta rules.
    let mut file_h = File::open("assets/opengex-syntax.txt").unwrap();
    let mut source = String::new();
    file_h.read_to_string(&mut source).unwrap();
    let rules = stderr_unwrap(&source, syntax(&source));

    // Read cube.ogex.
    let mut file_h = File::open("assets/cube.ogex").unwrap();
    let mut source = String::new();
    file_h.read_to_string(&mut source).unwrap();
    let data = stderr_unwrap(&source, parse(&rules, &source));

    let v3 = |mut s: &mut Search| Ok([
        try!(s.f64("x")) as f32,
        try!(s.f64("y")) as f32,
        try!(s.f64("z")) as f32
    ]);

    let tx = vec![
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //bottom (0, 0, -1)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //right (1, 0, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //left (-1, 0, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //front (0, 1, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //back (0, -1, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
    ];

    let s = Search::new(&data);
    let vertex_data: Vec<Vertex> = stderr_unwrap(&source, s.for_bool("position", true,
        |ref mut s| {
            let mut vs = Vec::with_capacity(24);
            for t in &tx {
                vs.push(Vertex::new(try!(v3(s)), *t));
            }
            Ok(vs)
        }));

    let mesh = factory.create_mesh(&vertex_data);

    let index_data: &[u8] = &[
         0,  1,  2,  2,  3,  0, // top
         4,  6,  5,  6,  4,  7, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 14, 13, 14, 12, 16, // left
        16, 18, 17, 18, 16, 19, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = index_data.to_slice(factory, gfx::PrimitiveType::TriangleList);

    let texture = factory.create_texture_rgba8_static(1, 1, &[0x00_C0_A0_20]).unwrap();

    let sampler = factory.create_sampler(
        gfx::tex::SamplerInfo::new(gfx::tex::FilterMethod::Bilinear,
                                   gfx::tex::WrapMode::Clamp)
    );

    let program = {
        let vertex = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("../assets/cube_120.glslv")),
            glsl_150: Some(include_bytes!("../assets/cube_150.glslv")),
            .. gfx::ShaderSource::empty()
        };
        let fragment = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("../assets/cube_120.glslf")),
            glsl_150: Some(include_bytes!("../assets/cube_150.glslf")),
            .. gfx::ShaderSource::empty()
        };
        factory.link_program_source(vertex, fragment).unwrap()
    };

    let mut data = Params {
        u_model_view_proj: vecmath::mat4_id(),
        t_color: (texture, Some(sampler)),
        _r: std::marker::PhantomData,
    };

    let get_projection = |w: &PistonWindow<Sdl2Window>| {
        let draw_size = w.window.borrow().draw_size();
        CameraPerspective {
            fov: 90.0, near_clip: 0.1, far_clip: 1000.0,
            aspect_ratio: (draw_size.width as f32) / (draw_size.height as f32)
        }.projection()
    };

    let model = vecmath::mat4_id();
    let mut projection = get_projection(&events);
    let mut first_person = FirstPerson::new(
        [0.5, 0.5, 4.0],
        FirstPersonSettings::keyboard_wasd()
    );
    let state = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);

    for e in events {
        first_person.event(&e);

        e.draw_3d(|stream| {
            let args = e.render_args().unwrap();
            stream.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                }
            );
            data.u_model_view_proj = model_view_projection(
                model,
                first_person.camera(args.ext_dt).orthogonal(),
                projection
            );
            stream.draw(&(&mesh, slice.clone(), &program, &data, &state)).unwrap();
        });

        if let Some(_) = e.resize_args() {
            projection = get_projection(&e);
        }
    }
}
<|endoftext|>


<commit_before>extern crate ruroonga_client;
extern crate json_flex;

use json_flex::Unwrap;

use ruroonga_client as groonga;

fn create_table() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("table_create");
    command.set_argument(vec![("name", "Sites"),
                              ("flags","TABLE_HASH_KEY"),("key_type","ShortText")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("load url: {}", url);
    let res = request.load(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
}

fn create_column() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("column_create");
    command.set_argument(vec![("table", "Sites"),
                              ("name","title"),("type","ShortText")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("load url: {}", url);
    let res = request.load(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
}

fn load() {
    let data = r#"
[
{"_key":"http://example.org/","title":"This is test record 1!"},
{"_key":"http://example.net/","title":"test record 2."},
{"_key":"http://example.com/","title":"test test record three."},
{"_key":"http://example.net/afr","title":"test record four."},
{"_key":"http://example.org/aba","title":"test test test record five."},
{"_key":"http://example.com/rab","title":"test test test test record six."},
{"_key":"http://example.net/atv","title":"test test test record seven."},
{"_key":"http://example.org/gat","title":"test test record eight."},
{"_key":"http://example.com/vdw","title":"test test record nine."},
]"#;
    let mut request = groonga::HTTPRequest::new();
    let mut load_command = groonga::CommandQuery::new("load");
    load_command.set_argument(vec![("table", "Sites"),
                                   ("input_type","json"), ("values", data)]);
    let load_url = format!("http://localhost:10041{}", load_command.encode());
    println!("load url: {}", load_url);
    let load_res = request.load(load_url);
    let load_result = request.receive(&mut load_res.unwrap());
    println!("result: {}", load_result);
}

#[derive(Clone, Debug)]
struct Result {
    id: i64,
    key: String,
    title: String
}

fn main() {
    create_table();
    create_column();
    load();
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("select");
    command.set_argument(vec![("table", "Sites")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
    let mut decode = groonga::ResultParser::new(result);
    println!("status: {:?}", decode.status().unwrap());
    println!("start: {:?}", decode.start_time().unwrap());
    println!("elapsed: {:?}", decode.elapsed_time().unwrap());
    println!("matched columns: {:?}", decode.matched_columns().unwrap());
    let vec = decode.result().unwrap().pop().unwrap().unwrap_vec().clone();
    println!("index access: {:?}", vec[2]);
    // Read got response
    let mut result_vec: Vec<Result> = Vec::new();
    // Skip reading result header
    for v in decode.result().unwrap().pop().unwrap().unwrap_vec().iter().skip(2) {
        println!("{:?}", v);
        let raw = v.unwrap_vec();
        let elem = Result { id: raw[0].unwrap_i64().clone(),
                            key: raw[1].unwrap_string().clone(),
                            title: raw[2].unwrap_string().clone() };
        result_vec.push(elem.clone());
    }
    println!("{:?}", result_vec);
}
<commit_msg>example: Add error handling in get result phase<commit_after>extern crate ruroonga_client;
extern crate json_flex;

use json_flex::Unwrap;

use ruroonga_client as groonga;

fn create_table() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("table_create");
    command.set_argument(vec![("name", "Sites"),
                              ("flags","TABLE_HASH_KEY"),("key_type","ShortText")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("load url: {}", url);
    let res = request.load(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
}

fn create_column() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("column_create");
    command.set_argument(vec![("table", "Sites"),
                              ("name","title"),("type","ShortText")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("load url: {}", url);
    let res = request.load(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
}

fn load() {
    let data = r#"
[
{"_key":"http://example.org/","title":"This is test record 1!"},
{"_key":"http://example.net/","title":"test record 2."},
{"_key":"http://example.com/","title":"test test record three."},
{"_key":"http://example.net/afr","title":"test record four."},
{"_key":"http://example.org/aba","title":"test test test record five."},
{"_key":"http://example.com/rab","title":"test test test test record six."},
{"_key":"http://example.net/atv","title":"test test test record seven."},
{"_key":"http://example.org/gat","title":"test test record eight."},
{"_key":"http://example.com/vdw","title":"test test record nine."},
]"#;
    let mut request = groonga::HTTPRequest::new();
    let mut load_command = groonga::CommandQuery::new("load");
    load_command.set_argument(vec![("table", "Sites"),
                                   ("input_type","json"), ("values", data)]);
    let load_url = format!("http://localhost:10041{}", load_command.encode());
    println!("load url: {}", load_url);
    let load_res = request.load(load_url);
    let load_result = request.receive(&mut load_res.unwrap());
    println!("result: {}", load_result);
}

#[derive(Clone, Debug)]
struct Result {
    id: i64,
    key: String,
    title: String
}

fn main() {
    create_table();
    create_column();
    load();
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("select");
    command.set_argument(vec![("table", "Sites")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
    let mut decode = groonga::ResultParser::new(result);
    println!("status: {:?}", decode.status().unwrap());
    println!("start: {:?}", decode.start_time().unwrap());
    println!("elapsed: {:?}", decode.elapsed_time().unwrap());
    if decode.status().unwrap().clone() == 0 {
        println!("matched columns: {:?}", decode.matched_columns().unwrap());
        let vec = decode.result().unwrap().pop().unwrap().unwrap_vec().clone();
        println!("index access: {:?}", vec[2]);
        // Read got response
        let mut result_vec: Vec<Result> = Vec::new();
        // Skip reading result header
        for v in decode.result().unwrap().pop().unwrap().unwrap_vec().iter().skip(2) {
            println!("{:?}", v);
            let raw = v.unwrap_vec();
            let elem = Result { id: raw[0].unwrap_i64().clone(),
                                key: raw[1].unwrap_string().clone(),
                                title: raw[2].unwrap_string().clone() };
            result_vec.push(elem.clone());
        }
        println!("{:?}", result_vec);
    } else {
        println!("Couldn't get success response.")
    }
}
<|endoftext|>


<commit_before>use std::kinds::marker::ContravariantLifetime;
use std::mem;
use std::ptr;

use runtime::Object;
use {class, Id, IdVector, IntoIdVector};
use super::{INSCopying, INSObject};

pub struct NSRange {
	pub location: uint,
	pub length: uint,
}

pub struct NSEnumerator<'a, T> {
	id: Id<Object>,
	marker: ContravariantLifetime<'a>,
}

impl<'a, T> NSEnumerator<'a, T> {
	unsafe fn from_ptr(ptr: *Object) -> NSEnumerator<'a, T> {
		NSEnumerator { id: Id::from_ptr(ptr), marker: ContravariantLifetime }
	}
}

impl<'a, T> Iterator<&'a T> for NSEnumerator<'a, T> {
	fn next(&mut self) -> Option<&'a T> {
		unsafe {
			let obj = msg_send![self.id nextObject] as *T;
			obj.to_option()
		}
	}
}

pub trait INSArray<T: INSObject> : INSObject {
	fn count(&self) -> uint {
		let result = unsafe {
			msg_send![self count]
		};
		result as uint
	}

	fn object_at<'a>(&'a self, index: uint) -> &'a T {
		unsafe {
			let result = msg_send![self objectAtIndex:index] as *T;
			&*result
		}
	}

	fn object_enumerator<'a>(&'a self) -> NSEnumerator<'a, T> {
		unsafe {
			let result = msg_send![self objectEnumerator];
			NSEnumerator::from_ptr(result)
		}
	}

	unsafe fn from_refs(refs: &[&T]) -> Id<Self> {
		let cls = class::<Self>();
		let obj = msg_send![cls alloc];
		let obj = msg_send![obj initWithObjects:refs.as_ptr() count:refs.len()];
		Id::from_retained_ptr(obj as *Self)
	}

	fn from_vec(vec: Vec<Id<T>>) -> Id<Self> {
		let refs = vec.as_refs_slice();
		unsafe {
			INSArray::from_refs(refs)
		}
	}

	fn objects_in_range<'a>(&'a self, start: uint, len: uint) -> Vec<&'a T> {
		let vec: Vec<*T> = Vec::from_elem(len, ptr::null());
		let range = NSRange { location: start, length: len };
		unsafe {
			msg_send![self getObjects:vec.as_ptr() range:range];
			mem::transmute(vec)
		}
	}

	fn to_vec<'a>(&'a self) -> Vec<&'a T> {
		self.objects_in_range(0, self.count())
	}

	fn into_vec(array: Id<Self>) -> Vec<Id<T>> {
		let vec = array.to_vec();
		unsafe {
			vec.into_id_vec()
		}
	}
}

object_struct!(NSArray<T>)

impl<T: INSObject> INSArray<T> for NSArray<T> { }

impl<T> INSCopying<NSArray<T>> for NSArray<T> { }

impl<T: INSObject> Collection for NSArray<T> {
	fn len(&self) -> uint {
		self.count()
	}
}

#[cfg(test)]
mod tests {
	use {Id};
	use foundation::{INSObject, NSObject};
	use super::{INSArray, NSArray};

	#[test]
	fn test_count() {
		let empty_array: Id<NSArray<NSObject>> = INSObject::new();
		assert!(empty_array.count() == 0);

		let vec: Vec<Id<NSObject>> = Vec::from_fn(4, |_| INSObject::new());
		let array: Id<NSArray<NSObject>> = INSArray::from_vec(vec);
		assert!(array.count() == 4);
	}

	#[test]
	fn test_object_at() {
		let vec: Vec<Id<NSObject>> = Vec::from_fn(4, |_| INSObject::new());
		let array: Id<NSArray<NSObject>> = INSArray::from_vec(vec);
		assert!(array.object_at(0) != array.object_at(3));
	}

	#[test]
	fn test_object_enumerator() {
		let vec: Vec<Id<NSObject>> = Vec::from_fn(4, |_| INSObject::new());
		let array: Id<NSArray<NSObject>> = INSArray::from_vec(vec);

		assert!(array.object_enumerator().count() == 4);
		assert!(array.object_enumerator()
		             .enumerate()
		             .all(|(i, obj)| obj == array.object_at(i)));
	}

	#[test]
	fn test_objects_in_range() {
		let vec: Vec<Id<NSObject>> = Vec::from_fn(4, |_| INSObject::new());
		let array: Id<NSArray<NSObject>> = INSArray::from_vec(vec);

		let middle_objs = array.objects_in_range(1, 2);
		assert!(middle_objs.len() == 2);
		assert!(*middle_objs.get(0) == array.object_at(1));
		assert!(*middle_objs.get(1) == array.object_at(2));

		let empty_objs = array.objects_in_range(1, 0);
		assert!(empty_objs.len() == 0);

		let all_objs = array.objects_in_range(0, 4);
		assert!(all_objs.len() == 4);
	}

	#[test]
	fn test_into_vec() {
		let vec: Vec<Id<NSObject>> = Vec::from_fn(4, |_| INSObject::new());
		let array: Id<NSArray<NSObject>> = INSArray::from_vec(vec);

		let vec = INSArray::into_vec(array);
		assert!(vec.len() == 4);
	}
}
<commit_msg>Simplified NSArray tests with a sample_array function.<commit_after>use std::kinds::marker::ContravariantLifetime;
use std::mem;
use std::ptr;

use runtime::Object;
use {class, Id, IdVector, IntoIdVector};
use super::{INSCopying, INSObject};

pub struct NSRange {
	pub location: uint,
	pub length: uint,
}

pub struct NSEnumerator<'a, T> {
	id: Id<Object>,
	marker: ContravariantLifetime<'a>,
}

impl<'a, T> NSEnumerator<'a, T> {
	unsafe fn from_ptr(ptr: *Object) -> NSEnumerator<'a, T> {
		NSEnumerator { id: Id::from_ptr(ptr), marker: ContravariantLifetime }
	}
}

impl<'a, T> Iterator<&'a T> for NSEnumerator<'a, T> {
	fn next(&mut self) -> Option<&'a T> {
		unsafe {
			let obj = msg_send![self.id nextObject] as *T;
			obj.to_option()
		}
	}
}

pub trait INSArray<T: INSObject> : INSObject {
	fn count(&self) -> uint {
		let result = unsafe {
			msg_send![self count]
		};
		result as uint
	}

	fn object_at<'a>(&'a self, index: uint) -> &'a T {
		unsafe {
			let result = msg_send![self objectAtIndex:index] as *T;
			&*result
		}
	}

	fn object_enumerator<'a>(&'a self) -> NSEnumerator<'a, T> {
		unsafe {
			let result = msg_send![self objectEnumerator];
			NSEnumerator::from_ptr(result)
		}
	}

	unsafe fn from_refs(refs: &[&T]) -> Id<Self> {
		let cls = class::<Self>();
		let obj = msg_send![cls alloc];
		let obj = msg_send![obj initWithObjects:refs.as_ptr() count:refs.len()];
		Id::from_retained_ptr(obj as *Self)
	}

	fn from_vec(vec: Vec<Id<T>>) -> Id<Self> {
		let refs = vec.as_refs_slice();
		unsafe {
			INSArray::from_refs(refs)
		}
	}

	fn objects_in_range<'a>(&'a self, start: uint, len: uint) -> Vec<&'a T> {
		let vec: Vec<*T> = Vec::from_elem(len, ptr::null());
		let range = NSRange { location: start, length: len };
		unsafe {
			msg_send![self getObjects:vec.as_ptr() range:range];
			mem::transmute(vec)
		}
	}

	fn to_vec<'a>(&'a self) -> Vec<&'a T> {
		self.objects_in_range(0, self.count())
	}

	fn into_vec(array: Id<Self>) -> Vec<Id<T>> {
		let vec = array.to_vec();
		unsafe {
			vec.into_id_vec()
		}
	}
}

object_struct!(NSArray<T>)

impl<T: INSObject> INSArray<T> for NSArray<T> { }

impl<T> INSCopying<NSArray<T>> for NSArray<T> { }

impl<T: INSObject> Collection for NSArray<T> {
	fn len(&self) -> uint {
		self.count()
	}
}

#[cfg(test)]
mod tests {
	use {Id};
	use foundation::{INSObject, NSObject};
	use super::{INSArray, NSArray};

	fn sample_array(len: uint) -> Id<NSArray<NSObject>> {
		let vec: Vec<Id<NSObject>> = Vec::from_fn(len, |_| INSObject::new());
		INSArray::from_vec(vec)
	}

	#[test]
	fn test_count() {
		let empty_array: Id<NSArray<NSObject>> = INSObject::new();
		assert!(empty_array.count() == 0);

		let array = sample_array(4);
		assert!(array.count() == 4);
	}

	#[test]
	fn test_object_at() {
		let array = sample_array(4);
		assert!(array.object_at(0) != array.object_at(3));
	}

	#[test]
	fn test_object_enumerator() {
		let array = sample_array(4);

		assert!(array.object_enumerator().count() == 4);
		assert!(array.object_enumerator()
		             .enumerate()
		             .all(|(i, obj)| obj == array.object_at(i)));
	}

	#[test]
	fn test_objects_in_range() {
		let array = sample_array(4);

		let middle_objs = array.objects_in_range(1, 2);
		assert!(middle_objs.len() == 2);
		assert!(*middle_objs.get(0) == array.object_at(1));
		assert!(*middle_objs.get(1) == array.object_at(2));

		let empty_objs = array.objects_in_range(1, 0);
		assert!(empty_objs.len() == 0);

		let all_objs = array.objects_in_range(0, 4);
		assert!(all_objs.len() == 4);
	}

	#[test]
	fn test_into_vec() {
		let array = sample_array(4);

		let vec = INSArray::into_vec(array);
		assert!(vec.len() == 4);
	}
}
<|endoftext|>