<commit_before>// Copyright 2015 Michael 'ExpHP' Lamparski
//
// Licensed under the terms of the MIT License, available at:
//  http://opensource.org/licenses/MIT
// and also included in the file COPYING at the root of this distribution.
// This file may not be copied, modified, or distributed except according
// to those terms.

extern crate num;
extern crate test;

use std::collections::hash_map::{HashMap,Hasher};
use std::default::Default;
use std::num::{ToPrimitive,FromPrimitive}; // and regret it
use std::hash::Hash;
use std::ops::Shr;

use num::bigint::{ToBigUint,BigUint};
use num::{Zero,One,Integer};
use std::num::Float;

use test::Bencher;

/// Computes the greatest common divisor of two numbers using Euclid's method.
/// Behavior unspecified for negative numbers.
pub fn gcd<T>(a: T,  b: T) -> T
 where T: Clone + Zero + Integer,
{
	if (a == Zero::zero()) {
		b
	} else {
		gcd(b % a.clone(), a)
	}
}

/// Performs an integer square root, returning the largest integer whose square is not
///  greater than the argument.
pub fn isqrt<T>(n: T) -> T
 where T: Clone + FromPrimitive + ToPrimitive + Zero + One + Integer + Shr<usize, Output=T>,
{
	isqrt_fast(n.clone()).or_else(
		|| Some(isqrt_safe(n.clone()))
	).unwrap()
}

/// Used to convert an integral literal into an arbitrary type.
/// For zero and one, `num::Zero::zero()` and `num::One::one()` is preferred when they
///  are used as the additive/multiplicative identity, and `literal` is used otherwise.
#[inline]
pub fn literal<T>(n: isize) -> T
 where T: FromPrimitive,
{
	FromPrimitive::from_int(n).unwrap()
}

//-------------------------------
// isqrt helper methods

fn isqrt_fast<T>(x: T) -> Option<T>
 where T: FromPrimitive + ToPrimitive,
{
	x.to_f64().and_then(|f| {
		// Mantissa is 52 bits, and the square root takes half as many bits, so this
		//  may be a bit conservative.  The main concern is to avoid handling very
		//  large BigInts which may lose more than half of their precision.
		if f > 20f64.exp2() {
			None                 // Number too large, bail out!
		} else {
			FromPrimitive::from_f64(f.sqrt().floor())
		}
	})
}

fn isqrt_safe<T>(n: T) -> T
 where T: Clone + FromPrimitive + ToPrimitive + Zero + One + Integer + Shr<usize, Output=T>,
{
	// NOTE: while I'd like to remove the Shr bound, replacing '>> 1' with '/ 2' makes this
	//       algorithm take twice as long for BigInts :/
	if n.is_zero() { return Zero::zero(); }
	let mut x = n.clone();
	let mut y = (x.clone() + n.clone() / x.clone()) >> literal(1);
	while y < x {
		x = y.clone();
		y = (x.clone() + n.clone() / x.clone()) >> literal(1);
	}
	return x;
}

#[bench]
fn bench_fast(b: &mut Bencher) {
	b.iter(|| {
		(0us..1000us).map(|a| {isqrt_fast::<usize>(a).unwrap()}).collect::<Vec<usize>>()
	})
}

#[bench]
fn bench_safe(b: &mut Bencher) {
	b.iter(|| {
		(0us..1000us).map(isqrt_safe::<usize>).collect::<Vec<usize>>()
	})
}

#[bench]
fn bench_safe_bigint(b: &mut Bencher) {
	b.iter(|| {
		(0us..1000us).map(|a| isqrt_safe::<BigUint>(FromPrimitive::from_uint(a).unwrap())).collect::<Vec<BigUint>>()
	})
}

#[bench]
fn bench_safe_massive_bigint(b: &mut Bencher) {
	use std::rand::XorShiftRng;
	use num::bigint::RandBigInt;
	let mut r = XorShiftRng::new_unseeded();
	b.iter(|| {
		(0us..100us).map(|_| {
			isqrt_safe::<BigUint>(r.gen_biguint(100us))
		}).collect::<Vec<BigUint>>()
	})
}

#[test]
fn test_isqrt_consistency()
{
	(0us..1000).map(|x| {
		let bigX = x.to_biguint().unwrap();
		assert_eq!(isqrt_fast(x),            Some(isqrt_safe(x)));
		assert_eq!(isqrt_fast(bigX.clone()), Some(isqrt_safe(bigX.clone())));
	});
}

#[cfg(test)]
mod tests {
	extern crate test;
	use super::*;
	use std::num::FromPrimitive;
	use std::num::ToPrimitive;
	use num::bigint::{ToBigUint,BigUint};

	// need to test isqrt with BigInt more rigorously

}
<commit_msg>Fix test that wasn't actually running<commit_after>// Copyright 2015 Michael 'ExpHP' Lamparski
//
// Licensed under the terms of the MIT License, available at:
//  http://opensource.org/licenses/MIT
// and also included in the file COPYING at the root of this distribution.
// This file may not be copied, modified, or distributed except according
// to those terms.

extern crate num;
extern crate test;

use std::collections::hash_map::{HashMap,Hasher};
use std::default::Default;
use std::num::{ToPrimitive,FromPrimitive}; // and regret it
use std::hash::Hash;
use std::ops::Shr;

use num::bigint::{ToBigUint,BigUint};
use num::{Zero,One,Integer};
use std::num::Float;

use test::Bencher;

/// Computes the greatest common divisor of two numbers using Euclid's method.
/// Behavior unspecified for negative numbers.
pub fn gcd<T>(a: T,  b: T) -> T
 where T: Clone + Zero + Integer,
{
	if (a == Zero::zero()) {
		b
	} else {
		gcd(b % a.clone(), a)
	}
}

/// Performs an integer square root, returning the largest integer whose square is not
///  greater than the argument.
pub fn isqrt<T>(n: T) -> T
 where T: Clone + FromPrimitive + ToPrimitive + Zero + One + Integer + Shr<usize, Output=T>,
{
	isqrt_fast(n.clone()).or_else(
		|| Some(isqrt_safe(n.clone()))
	).unwrap()
}

/// Used to convert an integral literal into an arbitrary type.
/// For zero and one, `num::Zero::zero()` and `num::One::one()` is preferred when they
///  are used as the additive/multiplicative identity, and `literal` is used otherwise.
#[inline]
pub fn literal<T>(n: isize) -> T
 where T: FromPrimitive,
{
	FromPrimitive::from_int(n).unwrap()
}

//-------------------------------
// isqrt helper methods

fn isqrt_fast<T>(x: T) -> Option<T>
 where T: FromPrimitive + ToPrimitive,
{
	x.to_f64().and_then(|f| {
		// Mantissa is 52 bits, and the square root takes half as many bits, so this
		//  may be a bit conservative.  The main concern is to avoid handling very
		//  large BigInts which may lose more than half of their precision.
		if f > 20f64.exp2() {
			None                 // Number too large, bail out!
		} else {
			FromPrimitive::from_f64(f.sqrt().floor())
		}
	})
}

fn isqrt_safe<T>(n: T) -> T
 where T: Clone + FromPrimitive + ToPrimitive + Zero + One + Integer + Shr<usize, Output=T>,
{
	// NOTE: while I'd like to remove the Shr bound, replacing '>> 1' with '/ 2' makes this
	//       algorithm take twice as long for BigInts :/
	if n.is_zero() { return Zero::zero(); }
	let mut x = n.clone();
	let mut y = (x.clone() + n.clone() / x.clone()) >> literal(1);
	while y < x {
		x = y.clone();
		y = (x.clone() + n.clone() / x.clone()) >> literal(1);
	}
	return x;
}

#[bench]
fn bench_fast(b: &mut Bencher) {
	b.iter(|| {
		(0us..1000us).map(|a| {isqrt_fast::<usize>(a).unwrap()}).collect::<Vec<usize>>()
	})
}

#[bench]
fn bench_safe(b: &mut Bencher) {
	b.iter(|| {
		(0us..1000us).map(isqrt_safe::<usize>).collect::<Vec<usize>>()
	})
}

#[bench]
fn bench_safe_bigint(b: &mut Bencher) {
	b.iter(|| {
		(0us..1000us).map(|a| isqrt_safe::<BigUint>(FromPrimitive::from_uint(a).unwrap())).collect::<Vec<BigUint>>()
	})
}

#[bench]
fn bench_safe_massive_bigint(b: &mut Bencher) {
	use std::rand::XorShiftRng;
	use num::bigint::RandBigInt;
	let mut r = XorShiftRng::new_unseeded();
	b.iter(|| {
		(0us..100us).map(|_| {
			isqrt_safe::<BigUint>(r.gen_biguint(100us))
		}).collect::<Vec<BigUint>>()
	})
}

#[test]
fn test_isqrt_consistency()
{
	(0us..1000).map(|x| {
		let bigX = x.to_biguint().unwrap();
		assert_eq!(isqrt_fast(x),            Some(isqrt_safe(x)));
		assert_eq!(isqrt_fast(bigX.clone()), Some(isqrt_safe(bigX.clone())));
	}).collect::<Vec<_>>();
}

#[cfg(test)]
mod tests {
	extern crate test;
	use super::*;
	use std::num::FromPrimitive;
	use std::num::ToPrimitive;
	use num::bigint::{ToBigUint,BigUint};

	// need to test isqrt with BigInt more rigorously

}
<|endoftext|>


<commit_before>#![cfg(test)]

use std::fs;
use std::io::Read;
use std::path::Path;

use crate::model;

fn parse_recursively(path: &Path) {
    let file_name = path
        .file_name()
        .expect("file_name")
        .to_str()
        .expect("to_str");
    if path.is_dir() {
        for entry in fs::read_dir(path).expect("read_dir") {
            parse_recursively(&entry.expect("entry").path());
        }
    } else if file_name.ends_with(".proto") {
        println!("checking {}", path.display());
        let mut content = String::new();
        fs::File::open(path)
            .expect("open")
            .read_to_string(&mut content)
            .expect("read");
        model::FileDescriptor::parse(&content).expect("parse");
    }
}

#[test]
fn test() {
    let path = &Path::new("../google-protobuf");
    parse_recursively(&Path::new(path));
}
<commit_msg>In parse tests, check the directory we are parsing is not empty<commit_after>#![cfg(test)]

use std::fs;
use std::io::Read;
use std::path::Path;

use crate::model;

fn parse_recursively(path: &Path) {
    assert!(path.exists());

    let file_name = path
        .file_name()
        .expect("file_name")
        .to_str()
        .expect("to_str");
    if path.is_dir() {
        for entry in fs::read_dir(path).expect("read_dir") {
            parse_recursively(&entry.expect("entry").path());
        }
    } else if file_name.ends_with(".proto") {
        println!("checking {}", path.display());
        let mut content = String::new();
        fs::File::open(path)
            .expect("open")
            .read_to_string(&mut content)
            .expect("read");
        model::FileDescriptor::parse(&content).expect("parse");
    }
}

#[test]
fn test() {
    let path = &Path::new("../google-protobuf");
    parse_recursively(&Path::new(path));
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::iter::range_step;
use stb_image::image as stb_image;
use png;

// FIXME: Images must not be copied every frame. Instead we should atomically
// reference count them.
pub type Image = png::Image;

static TEST_IMAGE: &'static [u8] = include_bin!("test.jpeg");

pub fn test_image_bin() -> Vec<u8> {
    TEST_IMAGE.iter().map(|&x| x).collect()
}

// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this.
fn byte_swap(data: &mut [u8]) {
    let length = data.len();
    for i in range_step(0, length, 4) {
        let r = data[i + 2];
        data[i + 2] = data[i + 0];
        data[i + 0] = r;
    }
}

// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this.
fn byte_swap_and_premultiply(data: &mut [u8]) {
    let length = data.len();
    for i in range_step(0, length, 4) {
        let r = data[i + 2];
        let g = data[i + 1];
        let b = data[i + 0];
        let a = data[i + 3];
        data[i + 0] = ((r as u32) * (a as u32) / 255) as u8;
        data[i + 1] = ((g as u32) * (a as u32) / 255) as u8;
        data[i + 2] = ((b as u32) * (a as u32) / 255) as u8;
    }
}

pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
    if buffer.len() == 0 {
        return None;
    }

    if png::is_png(buffer) {
        match png::load_png_from_memory(buffer) {
            Ok(mut png_image) => {
                match png_image.pixels {
                    png::RGB8(ref mut data) => byte_swap(data.as_mut_slice()),
                    png::RGBA8(ref mut data) => {
                        byte_swap_and_premultiply(data.as_mut_slice())
                    }
                    _ => {}
                }
                Some(png_image)
            }
            Err(_err) => None,
        }
    } else {
        // For non-png images, we use stb_image
        // Can't remember why we do this. Maybe it's what cairo wants
        static FORCE_DEPTH: uint = 4;

        match stb_image::load_from_memory_with_depth(buffer, FORCE_DEPTH, true) {
            stb_image::ImageU8(mut image) => {
                assert!(image.depth == 4);
                byte_swap(image.data.as_mut_slice());
                Some(png::Image {
                    width: image.width as u32,
                    height: image.height as u32,
                    pixels: png::RGBA8(image.data)
                })
            }
            stb_image::ImageF32(_image) => fail!("HDR images not implemented"),
            stb_image::Error(_) => None
        }
    }
}
<commit_msg>auto merge of #3872 : kmcallister/servo/stb-error, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::iter::range_step;
use stb_image::image as stb_image;
use png;

// FIXME: Images must not be copied every frame. Instead we should atomically
// reference count them.
pub type Image = png::Image;

static TEST_IMAGE: &'static [u8] = include_bin!("test.jpeg");

pub fn test_image_bin() -> Vec<u8> {
    TEST_IMAGE.iter().map(|&x| x).collect()
}

// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this.
fn byte_swap(data: &mut [u8]) {
    let length = data.len();
    for i in range_step(0, length, 4) {
        let r = data[i + 2];
        data[i + 2] = data[i + 0];
        data[i + 0] = r;
    }
}

// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this.
fn byte_swap_and_premultiply(data: &mut [u8]) {
    let length = data.len();
    for i in range_step(0, length, 4) {
        let r = data[i + 2];
        let g = data[i + 1];
        let b = data[i + 0];
        let a = data[i + 3];
        data[i + 0] = ((r as u32) * (a as u32) / 255) as u8;
        data[i + 1] = ((g as u32) * (a as u32) / 255) as u8;
        data[i + 2] = ((b as u32) * (a as u32) / 255) as u8;
    }
}

pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
    if buffer.len() == 0 {
        return None;
    }

    if png::is_png(buffer) {
        match png::load_png_from_memory(buffer) {
            Ok(mut png_image) => {
                match png_image.pixels {
                    png::RGB8(ref mut data) => byte_swap(data.as_mut_slice()),
                    png::RGBA8(ref mut data) => {
                        byte_swap_and_premultiply(data.as_mut_slice())
                    }
                    _ => {}
                }
                Some(png_image)
            }
            Err(_err) => None,
        }
    } else {
        // For non-png images, we use stb_image
        // Can't remember why we do this. Maybe it's what cairo wants
        static FORCE_DEPTH: uint = 4;

        match stb_image::load_from_memory_with_depth(buffer, FORCE_DEPTH, true) {
            stb_image::ImageU8(mut image) => {
                assert!(image.depth == 4);
                byte_swap(image.data.as_mut_slice());
                Some(png::Image {
                    width: image.width as u32,
                    height: image.height as u32,
                    pixels: png::RGBA8(image.data)
                })
            }
            stb_image::ImageF32(_image) => {
                error!("HDR images not implemented");
                None
            }
            stb_image::Error(e) => {
                error!("stb_image failed: {}", e);
                None
            }
        }
    }
}
<|endoftext|>


<commit_before>use parser;
use normalize::resolve::resolve;
use normalize::NormResult;
use lexer::dfa::interpret;
use grammar::parse_tree::Grammar;
use test_util;

fn validate_grammar(grammar: &str) -> NormResult<Grammar> {
    let parsed_grammar = parser::parse_grammar(&grammar).expect("parse grammar");
    let parsed_grammar = resolve(parsed_grammar).expect("resolve");
    super::validate(parsed_grammar)
}

fn check_err(expected_err: &str,
             grammar: &str,
             span: &str) {
    let err = validate_grammar(&grammar).unwrap_err();
    test_util::check_norm_err(expected_err, span, err);
}

fn check_intern_token(grammar: &str,
                      expected_tokens: Vec<(&'static str, &'static str)>)
{
    let parsed_grammar = validate_grammar(&grammar).expect("validate");
    let intern_token = parsed_grammar.intern_token().expect("intern_token");
    println!("intern_token: {:?}", intern_token);
    for (input, expected_user_name) in expected_tokens {
        let actual_user_name =
            interpret::interpret(&intern_token.dfa, input)
            .map(|(index, text)| {
                let user_name = intern_token.match_entries[index.index()].user_name;
                (user_name, text)
            });
        let actual_user_name = format!("{:?}", actual_user_name);
        if expected_user_name != actual_user_name {
            panic!("input `{}` matched `{}` but we expected `{}`",
                   input,
                   actual_user_name,
                   expected_user_name);
        }
    }
}

#[test]
fn unknown_terminal() {
    check_err(
        r#"terminal `"\+"` does not have a pattern defined for it"#,
        r#"grammar; extern { enum Term { } } X = X "+";"#,
        r#"                                        ~~~ "#);
}

#[test]
fn unknown_id_terminal() {
    check_err(
        r#"terminal `"foo"` does not have a pattern defined for it"#,
        r#"grammar; extern { enum Term { } } X = X "foo";"#,
        r#"                                        ~~~~~ "#);
}

#[test]
fn tick_input_lifetime_already_declared() {
    check_err(
        r#".*the `'input` lifetime is implicit and cannot be declared"#,
        r#"grammar<'input>; X = X "foo";"#,
        r#"~~~~~~~                      "#);
}

#[test]
fn input_parameter_already_declared() {
    check_err(
        r#".*the `input` parameter is implicit and cannot be declared"#,
        r#"grammar(input:u32); X = X "foo";"#,
        r#"~~~~~~~                         "#);
}

#[test]
fn invalid_regular_expression_unterminated_group() {
    check_err(
        r#"Unclosed parenthesis"#,
        r#"grammar; X = X r"(123";"#,
        r#"               ~~~~~~~ "#);
}

#[test]
fn quoted_literals() {
    check_intern_token(
        r#"grammar; X = X "+" "-" "foo" "(" ")";"#,
        vec![("+", r#"Some(("+", "+"))"#),
             ("-", r#"Some(("-", "-"))"#),
             ("(", r#"Some(("(", "("))"#),
             (")", r#"Some((")", ")"))"#),
             ("foo", r#"Some(("foo", "foo"))"#),
             ("<", r#"None"#)]);
}

#[test]
fn regex_literals() {
    check_intern_token(
        r#"grammar; X = X r"[a-z]+" r"[0-9]+";"#,
        vec![
            ("a", r##"Some((r#"[a-z]+"#, "a"))"##),
            ("def", r##"Some((r#"[a-z]+"#, "def"))"##),
            ("1", r##"Some((r#"[0-9]+"#, "1"))"##),
            ("9123456", r##"Some((r#"[0-9]+"#, "9123456"))"##),
                ]);
}

#[test]
fn match_mappings() {
    check_intern_token(
        r#"grammar; match { r"(?i)begin" => "BEGIN" } else { "abc" => ALPHA } X = "BEGIN" ALPHA;"#,
        vec![
            ("BEGIN", r##"Some(("BEGIN", "BEGIN"))"##),
            ("begin", r##"Some(("BEGIN", "begin"))"##),
            ("abc", r#"Some((ALPHA, "abc"))"#),
                ]);
}

#[test]
fn invalid_match_literal() {
    check_err(
        r#"terminal `"foo"` does not have a match mapping defined for it"#,
        r#"grammar; match { r"(?i)begin" => "BEGIN" } X = "foo";"#,
        r#"                                               ~~~~~ "#);
}

#[test]
fn match_catch_all() {
    let grammar = r#"grammar; match { r"(?i)begin" => "BEGIN", _ } X = "foo";"#;
    assert!(validate_grammar(&grammar).is_ok())
}

#[test]
fn complex_match() {
    let grammar = r##"
        grammar;
        match {
            "abc"        => "ABC",
            r"(?i)begin" => BEGIN
        }

        pub Query: String = {
            "ABC" BEGIN => String::from("Success")
        };
"##;
    assert!(validate_grammar(&grammar).is_ok())
}
<commit_msg>add various `match` tests<commit_after>use parser;
use normalize::resolve::resolve;
use normalize::NormResult;
use lexer::dfa::interpret;
use grammar::parse_tree::Grammar;
use test_util;

fn validate_grammar(grammar: &str) -> NormResult<Grammar> {
    let parsed_grammar = parser::parse_grammar(&grammar).expect("parse grammar");
    let parsed_grammar = resolve(parsed_grammar).expect("resolve");
    super::validate(parsed_grammar)
}

fn check_err(expected_err: &str,
             grammar: &str,
             span: &str) {
    let err = validate_grammar(&grammar).unwrap_err();
    test_util::check_norm_err(expected_err, span, err);
}

fn check_intern_token(grammar: &str,
                      expected_tokens: Vec<(&'static str, &'static str)>)
{
    let parsed_grammar = validate_grammar(&grammar).expect("validate");
    let intern_token = parsed_grammar.intern_token().expect("intern_token");
    println!("intern_token: {:?}", intern_token);
    for (input, expected_user_name) in expected_tokens {
        let actual_user_name =
            interpret::interpret(&intern_token.dfa, input)
            .map(|(index, text)| {
                let user_name = intern_token.match_entries[index.index()].user_name;
                (user_name, text)
            });
        let actual_user_name = format!("{:?}", actual_user_name);
        if expected_user_name != actual_user_name {
            panic!("input `{}` matched `{}` but we expected `{}`",
                   input,
                   actual_user_name,
                   expected_user_name);
        }
    }
}

#[test]
fn unknown_terminal() {
    check_err(
        r#"terminal `"\+"` does not have a pattern defined for it"#,
        r#"grammar; extern { enum Term { } } X = X "+";"#,
        r#"                                        ~~~ "#);
}

#[test]
fn unknown_id_terminal() {
    check_err(
        r#"terminal `"foo"` does not have a pattern defined for it"#,
        r#"grammar; extern { enum Term { } } X = X "foo";"#,
        r#"                                        ~~~~~ "#);
}

#[test]
fn tick_input_lifetime_already_declared() {
    check_err(
        r#".*the `'input` lifetime is implicit and cannot be declared"#,
        r#"grammar<'input>; X = X "foo";"#,
        r#"~~~~~~~                      "#);
}

#[test]
fn input_parameter_already_declared() {
    check_err(
        r#".*the `input` parameter is implicit and cannot be declared"#,
        r#"grammar(input:u32); X = X "foo";"#,
        r#"~~~~~~~                         "#);
}

#[test]
fn invalid_regular_expression_unterminated_group() {
    check_err(
        r#"Unclosed parenthesis"#,
        r#"grammar; X = X r"(123";"#,
        r#"               ~~~~~~~ "#);
}

#[test]
fn quoted_literals() {
    check_intern_token(
        r#"grammar; X = X "+" "-" "foo" "(" ")";"#,
        vec![("+", r#"Some(("+", "+"))"#),
             ("-", r#"Some(("-", "-"))"#),
             ("(", r#"Some(("(", "("))"#),
             (")", r#"Some((")", ")"))"#),
             ("foo", r#"Some(("foo", "foo"))"#),
             ("<", r#"None"#)]);
}

#[test]
fn regex_literals() {
    check_intern_token(
        r#"grammar; X = X r"[a-z]+" r"[0-9]+";"#,
        vec![
            ("a", r##"Some((r#"[a-z]+"#, "a"))"##),
            ("def", r##"Some((r#"[a-z]+"#, "def"))"##),
            ("1", r##"Some((r#"[0-9]+"#, "1"))"##),
            ("9123456", r##"Some((r#"[0-9]+"#, "9123456"))"##),
                ]);
}

/// Basic test for match mappings.
#[test]
fn match_mappings() {
    check_intern_token(
        r#"grammar; match { r"(?i)begin" => "BEGIN" } else { "abc" => ALPHA } X = "BEGIN" ALPHA;"#,
        vec![
            ("BEGIN", r##"Some(("BEGIN", "BEGIN"))"##),
            ("begin", r##"Some(("BEGIN", "begin"))"##),
            ("abc", r#"Some((ALPHA, "abc"))"#),
                ]);
}

/// Match mappings, exercising precedence. Here the ID regex *would*
/// be ambiguous with the begin regex.
#[test]
fn match_precedence() {
    check_intern_token(
        r#"grammar; match { r"(?i)begin" => "BEGIN" } else { r"\w+" => ID } X = ();"#,
        vec![
            ("BEGIN", r##"Some(("BEGIN", "BEGIN"))"##),
            ("begin", r##"Some(("BEGIN", "begin"))"##),
            ("abc", r#"Some((ID, "abc"))"#),
                ]);
}

/// Test that, without a `catch-all`, using unrecognized literals is an error.
#[test]
fn invalid_match_literal() {
    check_err(
        r#"terminal `"foo"` does not have a match mapping defined for it"#,
        r#"grammar; match { r"(?i)begin" => "BEGIN" } X = "foo";"#,
        r#"                                               ~~~~~ "#);
}

/// Test that, without a `catch-all`, using unrecognized literals is an error.
#[test]
fn invalid_match_regex_literal() {
    check_err(
        r##"terminal `r#"foo"#` does not have a match mapping defined for it"##,
        r#"grammar; match { r"(?i)begin" => "BEGIN" } X = r"foo";"#,
        r#"                                               ~~~~~~ "#);
}

/// Test that, with a catch-all, the previous two examples work.
#[test]
fn match_catch_all() {
    let grammar = r#"grammar; match { r"(?i)begin" => "BEGIN", _ } X = { "foo", r"foo" };"#;
    assert!(validate_grammar(&grammar).is_ok())
}

#[test]
fn complex_match() {
    let grammar = r##"
        grammar;
        match {
            "abc"        => "ABC",
            r"(?i)begin" => BEGIN
        }

        pub Query: String = {
            "ABC" BEGIN => String::from("Success")
        };
"##;
    assert!(validate_grammar(&grammar).is_ok())
}

/// Test that overlapping regular expressions are still forbidden within one level
/// of a match declaration.
#[test]
fn ambiguity_within_match() {
    check_err(
        r##"ambiguity detected between the terminal `r#"b"#` and the terminal `r#"\(\?i\)b"#`"##,
        r#"grammar; match { r"(?i)b" => "B", r"b" => "b" }"#,
        r#"                                  ~~~~~~~~~~~~ "#);
}

/// Test that using the **exact same regular expression** twice is
/// forbidden, even across multiple levels of the match expression.
/// No good reason to do that.
#[test]
fn same_literal_twice() {
    check_err(
        r##"multiple match entries for `r#"\(\?i\)b"#`"##,
        r#"grammar; match { r"(?i)b" => "B" } else { r"(?i)b" => "b" }"#,
        r#"                                          ~~~~~~~~~~~~~~~~ "#);
}
<|endoftext|>


<commit_before><commit_msg>Update example in comments<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;

use device::Device;

use OomError;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Pool from which descriptor sets are allocated from.
///
/// A pool has a maximum number of descriptor sets and a maximum number of descriptors (one value
/// per descriptor type) it can allocate.
pub struct DescriptorPool {
    pool: Mutex<vk::DescriptorPool>,
    device: Arc<Device>,
}

impl DescriptorPool {
    /// See the docs of new().
    // FIXME: capacity of the pool
    pub fn raw(device: &Arc<Device>) -> Result<DescriptorPool, OomError> {
        let vk = device.pointers();

        // FIXME: arbitrary
        let pool_sizes = vec![
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_STORAGE_BUFFER,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_SAMPLED_IMAGE,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                descriptorCount: 10,
            },
        ];

        let pool = unsafe {
            let infos = vk::DescriptorPoolCreateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
                pNext: ptr::null(),
                flags: vk::DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,   // TODO:
                maxSets: 100,       // TODO: let user choose
                poolSizeCount: pool_sizes.len() as u32,
                pPoolSizes: pool_sizes.as_ptr(),
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateDescriptorPool(device.internal_object(), &infos,
                                                      ptr::null(), &mut output)));
            output
        };

        Ok(DescriptorPool {
            pool: Mutex::new(pool),
            device: device.clone(),
        })
    }

    /// Initializes a new pool.
    ///
    /// # Panic
    ///
    /// - Panicks if the device or host ran out of memory.
    ///
    // FIXME: capacity of the pool
    #[inline]
    pub fn new(device: &Arc<Device>) -> Arc<DescriptorPool> {
        Arc::new(DescriptorPool::raw(device).unwrap())
    }

    /// Returns the device this pool was created from.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl SynchronizedVulkanObject for DescriptorPool {
    type Object = vk::DescriptorPool;

    #[inline]
    fn internal_object_guard(&self) -> MutexGuard<vk::DescriptorPool> {
        self.pool.lock().unwrap()
    }
}

impl Drop for DescriptorPool {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            let pool = self.pool.lock().unwrap();
            vk.DestroyDescriptorPool(self.device.internal_object(), *pool, ptr::null());
        }
    }
}

#[cfg(test)]
mod tests {
    use descriptor::descriptor_set::DescriptorPool;

    #[test]
    fn create() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = DescriptorPool::new(&device);
    }

    #[test]
    fn device() {
        let (device, _) = gfx_dev_and_queue!();
        let pool = DescriptorPool::new(&device);
        assert_eq!(&**pool.device() as *const _, &*device as *const _);
    }
}
<commit_msg>Added missing descriptor pool for the storage image type.<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;

use device::Device;

use OomError;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Pool from which descriptor sets are allocated from.
///
/// A pool has a maximum number of descriptor sets and a maximum number of descriptors (one value
/// per descriptor type) it can allocate.
pub struct DescriptorPool {
    pool: Mutex<vk::DescriptorPool>,
    device: Arc<Device>,
}

impl DescriptorPool {
    /// See the docs of new().
    // FIXME: capacity of the pool
    pub fn raw(device: &Arc<Device>) -> Result<DescriptorPool, OomError> {
        let vk = device.pointers();

        // FIXME: arbitrary
        let pool_sizes = vec![
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_STORAGE_BUFFER,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                 ty: vk::DESCRIPTOR_TYPE_STORAGE_IMAGE,
                 descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_SAMPLED_IMAGE,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                descriptorCount: 10,
            },
        ];

        let pool = unsafe {
            let infos = vk::DescriptorPoolCreateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
                pNext: ptr::null(),
                flags: vk::DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,   // TODO:
                maxSets: 100,       // TODO: let user choose
                poolSizeCount: pool_sizes.len() as u32,
                pPoolSizes: pool_sizes.as_ptr(),
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateDescriptorPool(device.internal_object(), &infos,
                                                      ptr::null(), &mut output)));
            output
        };

        Ok(DescriptorPool {
            pool: Mutex::new(pool),
            device: device.clone(),
        })
    }

    /// Initializes a new pool.
    ///
    /// # Panic
    ///
    /// - Panicks if the device or host ran out of memory.
    ///
    // FIXME: capacity of the pool
    #[inline]
    pub fn new(device: &Arc<Device>) -> Arc<DescriptorPool> {
        Arc::new(DescriptorPool::raw(device).unwrap())
    }

    /// Returns the device this pool was created from.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl SynchronizedVulkanObject for DescriptorPool {
    type Object = vk::DescriptorPool;

    #[inline]
    fn internal_object_guard(&self) -> MutexGuard<vk::DescriptorPool> {
        self.pool.lock().unwrap()
    }
}

impl Drop for DescriptorPool {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            let pool = self.pool.lock().unwrap();
            vk.DestroyDescriptorPool(self.device.internal_object(), *pool, ptr::null());
        }
    }
}

#[cfg(test)]
mod tests {
    use descriptor::descriptor_set::DescriptorPool;

    #[test]
    fn create() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = DescriptorPool::new(&device);
    }

    #[test]
    fn device() {
        let (device, _) = gfx_dev_and_queue!();
        let pool = DescriptorPool::new(&device);
        assert_eq!(&**pool.device() as *const _, &*device as *const _);
    }
}
<|endoftext|>


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

use rustc_hash::{FxHashMap, FxHashSet};
use arrayvec::ArrayVec;
use relative_path::RelativePathBuf;
use ra_db::{FileId, SourceRoot, CrateId};
use ra_syntax::{
    SyntaxNode, TreeArc,
    algo::generate,
    ast::{self, AstNode, NameOwner},
};
use ra_arena::{Arena, RawId, impl_arena_id};
use test_utils::tested_by;

use crate::{Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource};

impl ModuleSource {
    pub(crate) fn from_source_item_id(
        db: &impl HirDatabase,
        source_item_id: SourceItemId,
    ) -> ModuleSource {
        let module_syntax = db.file_item(source_item_id);
        if let Some(source_file) = ast::SourceFile::cast(&module_syntax) {
            ModuleSource::SourceFile(source_file.to_owned())
        } else if let Some(module) = ast::Module::cast(&module_syntax) {
            assert!(module.item_list().is_some(), "expected inline module");
            ModuleSource::Module(module.to_owned())
        } else {
            panic!("expected file or inline module")
        }
    }
}

#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Submodule {
    name: Name,
    is_declaration: bool,
    source: SourceItemId,
}

impl Submodule {
    pub(crate) fn submodules_query(
        db: &impl HirDatabase,
        source: SourceItemId,
    ) -> Arc<Vec<Submodule>> {
        db.check_canceled();
        let file_id = source.file_id;
        let file_items = db.file_items(file_id);
        let module_source = ModuleSource::from_source_item_id(db, source);
        let submodules = match module_source {
            ModuleSource::SourceFile(source_file) => {
                collect_submodules(file_id, &file_items, &*source_file)
            }
            ModuleSource::Module(module) => {
                collect_submodules(file_id, &file_items, module.item_list().unwrap())
            }
        };
        return Arc::new(submodules);

        fn collect_submodules(
            file_id: HirFileId,
            file_items: &SourceFileItems,
            root: &impl ast::ModuleItemOwner,
        ) -> Vec<Submodule> {
            root.items()
                .filter_map(|item| match item.kind() {
                    ast::ModuleItemKind::Module(m) => Some(m),
                    _ => None,
                })
                .filter_map(|module| {
                    let name = module.name()?.as_name();
                    if !module.has_semi() && module.item_list().is_none() {
                        tested_by!(name_res_works_for_broken_modules);
                        return None;
                    }
                    let sub = Submodule {
                        name,
                        is_declaration: module.has_semi(),
                        source: SourceItemId {
                            file_id,
                            item_id: Some(file_items.id_of(file_id, module.syntax())),
                        },
                    };
                    Some(sub)
                })
                .collect()
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ModuleId(RawId);
impl_arena_id!(ModuleId);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LinkId(RawId);
impl_arena_id!(LinkId);

/// Physically, rust source is organized as a set of files, but logically it is
/// organized as a tree of modules. Usually, a single file corresponds to a
/// single module, but it is not neccessarily always the case.
///
/// `ModuleTree` encapsulates the logic of transitioning from the fuzzy world of files
/// (which can have multiple parents) to the precise world of modules (which
/// always have one parent).
#[derive(Default, Debug, PartialEq, Eq)]
pub struct ModuleTree {
    mods: Arena<ModuleId, ModuleData>,
    links: Arena<LinkId, LinkData>,
}

#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ModuleData {
    source: SourceItemId,
    parent: Option<LinkId>,
    children: Vec<LinkId>,
}

#[derive(Hash, Debug, PartialEq, Eq)]
struct LinkData {
    source: SourceItemId,
    owner: ModuleId,
    name: Name,
    points_to: Vec<ModuleId>,
    problem: Option<Problem>,
}

impl ModuleTree {
    pub(crate) fn module_tree_query(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ModuleTree> {
        db.check_canceled();
        let mut res = ModuleTree::default();
        res.init_crate(db, crate_id);
        Arc::new(res)
    }

    pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a {
        self.mods.iter().map(|(id, _)| id)
    }

    pub(crate) fn find_module_by_source(&self, source: SourceItemId) -> Option<ModuleId> {
        let (res, _) = self.mods.iter().find(|(_, m)| m.source == source)?;
        Some(res)
    }

    fn init_crate(&mut self, db: &impl HirDatabase, crate_id: CrateId) {
        let crate_graph = db.crate_graph();
        let file_id = crate_graph.crate_root(crate_id);
        let source_root_id = db.file_source_root(file_id);

        let mut roots = FxHashMap::default();
        let mut visited = FxHashSet::default();

        let source_root = db.source_root(source_root_id);
        let source = SourceItemId {
            file_id: file_id.into(),
            item_id: None,
        };
        let module_id = self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source);
        roots.insert(file_id, module_id);
    }

    fn init_subtree(
        &mut self,
        db: &impl HirDatabase,
        source_root: &SourceRoot,
        visited: &mut FxHashSet<SourceItemId>,
        roots: &mut FxHashMap<FileId, ModuleId>,
        parent: Option<LinkId>,
        source: SourceItemId,
    ) -> ModuleId {
        visited.insert(source);
        let id = self.alloc_mod(ModuleData {
            source,
            parent,
            children: Vec::new(),
        });
        for sub in db.submodules(source).iter() {
            let link = self.alloc_link(LinkData {
                source: sub.source,
                name: sub.name.clone(),
                owner: id,
                points_to: Vec::new(),
                problem: None,
            });

            let (points_to, problem) = if sub.is_declaration {
                let (points_to, problem) = resolve_submodule(db, source.file_id, &sub.name);
                let points_to = points_to
                    .into_iter()
                    .map(|file_id| match roots.remove(&file_id) {
                        Some(module_id) => {
                            self.mods[module_id].parent = Some(link);
                            module_id
                        }
                        None => self.init_subtree(
                            db,
                            source_root,
                            visited,
                            roots,
                            Some(link),
                            SourceItemId {
                                file_id: file_id.into(),
                                item_id: None,
                            },
                        ),
                    })
                    .collect::<Vec<_>>();
                (points_to, problem)
            } else {
                let points_to =
                    self.init_subtree(db, source_root, visited, roots, Some(link), sub.source);
                (vec![points_to], None)
            };

            self.links[link].points_to = points_to;
            self.links[link].problem = problem;
        }
        id
    }

    fn alloc_mod(&mut self, data: ModuleData) -> ModuleId {
        self.mods.alloc(data)
    }

    fn alloc_link(&mut self, data: LinkData) -> LinkId {
        let owner = data.owner;
        let id = self.links.alloc(data);
        self.mods[owner].children.push(id);
        id
    }
}

impl ModuleId {
    pub(crate) fn source(self, tree: &ModuleTree) -> SourceItemId {
        tree.mods[self].source
    }
    pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
        tree.mods[self].parent
    }
    pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> {
        let link = self.parent_link(tree)?;
        Some(tree.links[link].owner)
    }
    pub(crate) fn crate_root(self, tree: &ModuleTree) -> ModuleId {
        generate(Some(self), move |it| it.parent(tree))
            .last()
            .unwrap()
    }
    pub(crate) fn child(self, tree: &ModuleTree, name: &Name) -> Option<ModuleId> {
        let link = tree.mods[self]
            .children
            .iter()
            .map(|&it| &tree.links[it])
            .find(|it| it.name == *name)?;
        Some(*link.points_to.first()?)
    }
    pub(crate) fn children<'a>(
        self,
        tree: &'a ModuleTree,
    ) -> impl Iterator<Item = (Name, ModuleId)> + 'a {
        tree.mods[self].children.iter().filter_map(move |&it| {
            let link = &tree.links[it];
            let module = *link.points_to.first()?;
            Some((link.name.clone(), module))
        })
    }
    pub(crate) fn problems(
        self,
        tree: &ModuleTree,
        db: &impl HirDatabase,
    ) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
        tree.mods[self]
            .children
            .iter()
            .filter_map(|&link| {
                let p = tree.links[link].problem.clone()?;
                let s = link.source(tree, db);
                let s = s.name().unwrap().syntax().to_owned();
                Some((s, p))
            })
            .collect()
    }
}

impl LinkId {
    pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId {
        tree.links[self].owner
    }
    pub(crate) fn name(self, tree: &ModuleTree) -> &Name {
        &tree.links[self].name
    }
    pub(crate) fn source(self, tree: &ModuleTree, db: &impl HirDatabase) -> TreeArc<ast::Module> {
        let syntax_node = db.file_item(tree.links[self].source);
        ast::Module::cast(&syntax_node).unwrap().to_owned()
    }
}

fn resolve_submodule(
    db: &impl HirDatabase,
    file_id: HirFileId,
    name: &Name,
) -> (Vec<FileId>, Option<Problem>) {
    // FIXME: handle submodules of inline modules properly
    let file_id = file_id.original_file(db);
    let source_root_id = db.file_source_root(file_id);
    let path = db.file_relative_path(file_id);
    let root = RelativePathBuf::default();
    let dir_path = path.parent().unwrap_or(&root);
    let mod_name = path.file_stem().unwrap_or("unknown");
    let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main";

    let file_mod = dir_path.join(format!("{}.rs", name));
    let dir_mod = dir_path.join(format!("{}/mod.rs", name));
    let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name));
    let mut candidates = ArrayVec::<[_; 2]>::new();
    if is_dir_owner {
        candidates.push(file_mod.clone());
        candidates.push(dir_mod);
    } else {
        candidates.push(file_dir_mod.clone());
    };
    let sr = db.source_root(source_root_id);
    let points_to = candidates
        .into_iter()
        .filter_map(|path| sr.files.get(&path))
        .map(|&it| it)
        .collect::<Vec<_>>();
    let problem = if points_to.is_empty() {
        Some(Problem::UnresolvedModule {
            candidate: if is_dir_owner { file_mod } else { file_dir_mod },
        })
    } else {
        None
    };
    (points_to, problem)
}
<commit_msg>remove dead code<commit_after>use std::sync::Arc;

use arrayvec::ArrayVec;
use relative_path::RelativePathBuf;
use ra_db::{FileId, SourceRoot, CrateId};
use ra_syntax::{
    SyntaxNode, TreeArc,
    algo::generate,
    ast::{self, AstNode, NameOwner},
};
use ra_arena::{Arena, RawId, impl_arena_id};
use test_utils::tested_by;

use crate::{Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource};

impl ModuleSource {
    pub(crate) fn from_source_item_id(
        db: &impl HirDatabase,
        source_item_id: SourceItemId,
    ) -> ModuleSource {
        let module_syntax = db.file_item(source_item_id);
        if let Some(source_file) = ast::SourceFile::cast(&module_syntax) {
            ModuleSource::SourceFile(source_file.to_owned())
        } else if let Some(module) = ast::Module::cast(&module_syntax) {
            assert!(module.item_list().is_some(), "expected inline module");
            ModuleSource::Module(module.to_owned())
        } else {
            panic!("expected file or inline module")
        }
    }
}

#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Submodule {
    name: Name,
    is_declaration: bool,
    source: SourceItemId,
}

impl Submodule {
    pub(crate) fn submodules_query(
        db: &impl HirDatabase,
        source: SourceItemId,
    ) -> Arc<Vec<Submodule>> {
        db.check_canceled();
        let file_id = source.file_id;
        let file_items = db.file_items(file_id);
        let module_source = ModuleSource::from_source_item_id(db, source);
        let submodules = match module_source {
            ModuleSource::SourceFile(source_file) => {
                collect_submodules(file_id, &file_items, &*source_file)
            }
            ModuleSource::Module(module) => {
                collect_submodules(file_id, &file_items, module.item_list().unwrap())
            }
        };
        return Arc::new(submodules);

        fn collect_submodules(
            file_id: HirFileId,
            file_items: &SourceFileItems,
            root: &impl ast::ModuleItemOwner,
        ) -> Vec<Submodule> {
            root.items()
                .filter_map(|item| match item.kind() {
                    ast::ModuleItemKind::Module(m) => Some(m),
                    _ => None,
                })
                .filter_map(|module| {
                    let name = module.name()?.as_name();
                    if !module.has_semi() && module.item_list().is_none() {
                        tested_by!(name_res_works_for_broken_modules);
                        return None;
                    }
                    let sub = Submodule {
                        name,
                        is_declaration: module.has_semi(),
                        source: SourceItemId {
                            file_id,
                            item_id: Some(file_items.id_of(file_id, module.syntax())),
                        },
                    };
                    Some(sub)
                })
                .collect()
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ModuleId(RawId);
impl_arena_id!(ModuleId);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LinkId(RawId);
impl_arena_id!(LinkId);

/// Physically, rust source is organized as a set of files, but logically it is
/// organized as a tree of modules. Usually, a single file corresponds to a
/// single module, but it is not neccessarily always the case.
///
/// `ModuleTree` encapsulates the logic of transitioning from the fuzzy world of files
/// (which can have multiple parents) to the precise world of modules (which
/// always have one parent).
#[derive(Default, Debug, PartialEq, Eq)]
pub struct ModuleTree {
    mods: Arena<ModuleId, ModuleData>,
    links: Arena<LinkId, LinkData>,
}

#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ModuleData {
    source: SourceItemId,
    parent: Option<LinkId>,
    children: Vec<LinkId>,
}

#[derive(Hash, Debug, PartialEq, Eq)]
struct LinkData {
    source: SourceItemId,
    owner: ModuleId,
    name: Name,
    points_to: Vec<ModuleId>,
    problem: Option<Problem>,
}

impl ModuleTree {
    pub(crate) fn module_tree_query(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ModuleTree> {
        db.check_canceled();
        let mut res = ModuleTree::default();
        res.init_crate(db, crate_id);
        Arc::new(res)
    }

    pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a {
        self.mods.iter().map(|(id, _)| id)
    }

    pub(crate) fn find_module_by_source(&self, source: SourceItemId) -> Option<ModuleId> {
        let (res, _) = self.mods.iter().find(|(_, m)| m.source == source)?;
        Some(res)
    }

    fn init_crate(&mut self, db: &impl HirDatabase, crate_id: CrateId) {
        let crate_graph = db.crate_graph();
        let file_id = crate_graph.crate_root(crate_id);
        let source_root_id = db.file_source_root(file_id);

        let source_root = db.source_root(source_root_id);
        let source = SourceItemId {
            file_id: file_id.into(),
            item_id: None,
        };
        self.init_subtree(db, &source_root, None, source);
    }

    fn init_subtree(
        &mut self,
        db: &impl HirDatabase,
        source_root: &SourceRoot,
        parent: Option<LinkId>,
        source: SourceItemId,
    ) -> ModuleId {
        let id = self.alloc_mod(ModuleData {
            source,
            parent,
            children: Vec::new(),
        });
        for sub in db.submodules(source).iter() {
            let link = self.alloc_link(LinkData {
                source: sub.source,
                name: sub.name.clone(),
                owner: id,
                points_to: Vec::new(),
                problem: None,
            });

            let (points_to, problem) = if sub.is_declaration {
                let (points_to, problem) = resolve_submodule(db, source.file_id, &sub.name);
                let points_to = points_to
                    .into_iter()
                    .map(|file_id| {
                        self.init_subtree(
                            db,
                            source_root,
                            Some(link),
                            SourceItemId {
                                file_id: file_id.into(),
                                item_id: None,
                            },
                        )
                    })
                    .collect::<Vec<_>>();
                (points_to, problem)
            } else {
                let points_to = self.init_subtree(db, source_root, Some(link), sub.source);
                (vec![points_to], None)
            };

            self.links[link].points_to = points_to;
            self.links[link].problem = problem;
        }
        id
    }

    fn alloc_mod(&mut self, data: ModuleData) -> ModuleId {
        self.mods.alloc(data)
    }

    fn alloc_link(&mut self, data: LinkData) -> LinkId {
        let owner = data.owner;
        let id = self.links.alloc(data);
        self.mods[owner].children.push(id);
        id
    }
}

impl ModuleId {
    pub(crate) fn source(self, tree: &ModuleTree) -> SourceItemId {
        tree.mods[self].source
    }
    pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
        tree.mods[self].parent
    }
    pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> {
        let link = self.parent_link(tree)?;
        Some(tree.links[link].owner)
    }
    pub(crate) fn crate_root(self, tree: &ModuleTree) -> ModuleId {
        generate(Some(self), move |it| it.parent(tree))
            .last()
            .unwrap()
    }
    pub(crate) fn child(self, tree: &ModuleTree, name: &Name) -> Option<ModuleId> {
        let link = tree.mods[self]
            .children
            .iter()
            .map(|&it| &tree.links[it])
            .find(|it| it.name == *name)?;
        Some(*link.points_to.first()?)
    }
    pub(crate) fn children<'a>(
        self,
        tree: &'a ModuleTree,
    ) -> impl Iterator<Item = (Name, ModuleId)> + 'a {
        tree.mods[self].children.iter().filter_map(move |&it| {
            let link = &tree.links[it];
            let module = *link.points_to.first()?;
            Some((link.name.clone(), module))
        })
    }
    pub(crate) fn problems(
        self,
        tree: &ModuleTree,
        db: &impl HirDatabase,
    ) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
        tree.mods[self]
            .children
            .iter()
            .filter_map(|&link| {
                let p = tree.links[link].problem.clone()?;
                let s = link.source(tree, db);
                let s = s.name().unwrap().syntax().to_owned();
                Some((s, p))
            })
            .collect()
    }
}

impl LinkId {
    pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId {
        tree.links[self].owner
    }
    pub(crate) fn name(self, tree: &ModuleTree) -> &Name {
        &tree.links[self].name
    }
    pub(crate) fn source(self, tree: &ModuleTree, db: &impl HirDatabase) -> TreeArc<ast::Module> {
        let syntax_node = db.file_item(tree.links[self].source);
        ast::Module::cast(&syntax_node).unwrap().to_owned()
    }
}

fn resolve_submodule(
    db: &impl HirDatabase,
    file_id: HirFileId,
    name: &Name,
) -> (Vec<FileId>, Option<Problem>) {
    // FIXME: handle submodules of inline modules properly
    let file_id = file_id.original_file(db);
    let source_root_id = db.file_source_root(file_id);
    let path = db.file_relative_path(file_id);
    let root = RelativePathBuf::default();
    let dir_path = path.parent().unwrap_or(&root);
    let mod_name = path.file_stem().unwrap_or("unknown");
    let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main";

    let file_mod = dir_path.join(format!("{}.rs", name));
    let dir_mod = dir_path.join(format!("{}/mod.rs", name));
    let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name));
    let mut candidates = ArrayVec::<[_; 2]>::new();
    if is_dir_owner {
        candidates.push(file_mod.clone());
        candidates.push(dir_mod);
    } else {
        candidates.push(file_dir_mod.clone());
    };
    let sr = db.source_root(source_root_id);
    let points_to = candidates
        .into_iter()
        .filter_map(|path| sr.files.get(&path))
        .map(|&it| it)
        .collect::<Vec<_>>();
    let problem = if points_to.is_empty() {
        Some(Problem::UnresolvedModule {
            candidate: if is_dir_owner { file_mod } else { file_dir_mod },
        })
    } else {
        None
    };
    (points_to, problem)
}
<|endoftext|>


<commit_before>use crate::prelude::*;

// --- KEYS --
const HEADER_CONTAINER: &str = "header_container";
const BODY_CONTAINER: &str = "body_container";
// --- KEYS --

/**
The `TabHeaderState` is used to store some callbacks that will be applied during template function.
Once the template function is called, they are no more used.
*/
#[derive(Default, AsAny)]
pub struct TabHeaderState {
    //Callback called when user click on the header of the tab (normally used to switch to the clicked tab). Only used during initialization
    on_header_click_callback: Option<Box<dyn 'static + Fn(&mut StatesContext, Point) -> bool>>,
    //Callback called when user click on the close button near the tab header (normally used to close the tab). Only used during initialization
    on_close_click_callback: Option<Box<dyn 'static + Fn(&mut StatesContext, Point) -> bool>>,
}

impl State for TabHeaderState {}

widget!(
    /// The `TabHeader` widget is used internally to managed tabs headers. Not meant for other uses.
    TabHeader<TabHeaderState>: ChangedHandler
    {
        /// Sets or shares the background property.
        background: Brush,

        /// Sets or shares the border radius property.
        border_radius: f64,

        /// Sets or shares the border thickness property.
        border_width: Thickness,

        /// Sets or shares the border brush property.
        border_brush: Brush,

        /// Sets or shares the padding property.
        padding: Thickness,

        /// Sets or shares the foreground property.
        foreground: Brush,

        /// Sets or shares the text property.
        text: String16,

        /// Sets or share the font size property.
        font_size: f64,

        /// Sets or shares the font property.
        font: String,

        /// Sets or shares the icon property.
        icon: String,

        /// Sets or shares the icon brush property.
        icon_brush: Brush,

        /// Sets or share the icon font size property.
        icon_size: f64,

        /// Sets or shares the icon font property.
        icon_font: String,

        /// Sets or shares the selected property.
        selected: bool,

        /// Sets or shares the spacing between icon and text.
        spacing: f64,

        /// Sets or shares the close button visibility.
        close_button: Visibility
    }
);

impl TabHeader {
    ///Set the callback that is called when user click on the header (generally used to switch tab)
    pub fn on_header_click<T: 'static + Fn(&mut StatesContext, Point) -> bool>(
        mut self,
        callback: T,
    ) -> Self {
        self.state.on_header_click_callback = Some(Box::new(callback));
        self
    }

    ///Set the callback that is called when user click on the close button near the header (generally used to close the tab)
    pub fn on_close_click<T: 'static + Fn(&mut StatesContext, Point) -> bool>(
        mut self,
        callback: T,
    ) -> Self {
        self.state.on_close_click_callback = Some(Box::new(callback));
        self
    }
}

impl Template for TabHeader {
    fn template(mut self, id: Entity, ctx: &mut BuildContext) -> Self {
        let mut toggle_button = ToggleButton::new()
            .background(id)
            .border_radius(id)
            .border_width(id)
            .border_brush(id)
            .padding(id)
            .foreground(id)
            .text(id)
            .font_size(id)
            .font(id)
            .icon(id)
            .icon_brush(id)
            .icon_size(id)
            .icon_font(id)
            .selected(id)
            .spacing(id);

        if let Some(callback) = self.state.on_header_click_callback.take() {
            toggle_button = toggle_button.on_click(callback);
        }

        let mut button = Button::new()
            .background(id)
            .border_radius(id)
            .border_width(id)
            .border_brush(id)
            .padding(id)
            .foreground(id)
            .font_size(id)
            .font(id)
            .icon(id)
            .icon_brush(id)
            .icon_size(id)
            .icon_font(id)
            .spacing(id)
            .text("X")
            .width(2)
            .visibility(("close_button", id));

        if let Some(callback) = self.state.on_close_click_callback.take() {
            button = button.on_click(callback);
        }
        //if self.close_button() == false {button = button.visibility(Visibility::Collapsed);}

        self.name("TabWidget")
            .selected(false)
            .height(36)
            .min_width(64)
            .background(colors::LYNCH_COLOR)
            .border_radius(4)
            .border_width(0)
            .border_brush("transparent")
            .padding((16, 0, 16, 0))
            .foreground(colors::LINK_WATER_COLOR)
            .text("Unnamed Tab")
            .font_size(fonts::FONT_SIZE_12)
            .font("Roboto Regular")
            .icon("")
            .icon_font("Material Icons")
            .icon_size(fonts::ICON_FONT_SIZE_12)
            .icon_brush(colors::LINK_WATER_COLOR)
            .spacing(8)
            .close_button(Visibility::Visible)
            .child(
                Stack::new()
                    .orientation("horizontal")
                    .child(toggle_button.build(ctx))
                    .child(button.build(ctx))
                    .build(ctx),
            )
    }
}

///Used to internally
enum TabWidgetAction {
    SelectByIndex(usize),
    SelectByBody(Entity),
    Add(String, Entity),
    Remove(Entity),
    SetCloseButtonVisibility(bool),
}
/**
Through the TabWidgetState it is possible to control the behaviour of TabWidget.
Nearly every called function on TabWidgetState will not be executed immediatly, but they are instead stored and executed during the update phase,
in the same order they are submitted.
*/
#[derive(Default, AsAny)]
pub struct TabWidgetState {
    ///Store all the pending actions. During the update call they will be resolved
    actions: Vec<TabWidgetAction>,

    header_container: Entity,
    body_container: Entity,

    tabs: Vec<(Entity, Entity)>, //Header , Body
    selected: usize,

    close_button_visibility: bool,
}

impl TabWidgetState {
    /**
    Switch the selected tab with one with the passed index.
    If the index is greater than the tab count, the last one will be selected.
    */
    pub fn select_by_index(&mut self, index: usize) {
        self.actions.push(TabWidgetAction::SelectByIndex(index));
    }
    /**
    Switch the selected tab with one with the passed body.
    If the no such body is found among the present tabs, nothing happen.
    */
    pub fn select_by_body(&mut self, entity: Entity) {
        self.actions.push(TabWidgetAction::SelectByBody(entity));
    }

    /**
    Remove the tab with the passed body.
    If the no such body is found among the present tabs, nothing happen.
    */
    pub fn remove_by_body(&mut self, entity: Entity) {
        self.actions.push(TabWidgetAction::Remove(entity));
    }

    ///Add a new tab to the widget.
    pub fn add_tab<T: Into<String>>(&mut self, header: T, body: Entity) {
        self.actions.push(TabWidgetAction::Add(header.into(), body));

        //At this point the tab has not been added yet, so we can check if len is == 0
        if self.tabs.len() == 0 {
            self.select_by_index(0);
        }
    }

    ///Set the close button visibility of all the tabs.
    pub fn set_close_button_visibility(&mut self, value: bool) {
        self.actions
            .push(TabWidgetAction::SetCloseButtonVisibility(value));
    }
    ///Get the close button visibility status
    pub fn get_close_button_visibility(&self) -> bool {
        self.close_button_visibility
    }

    /**
    Get the tab index associated with the passed body.
    If it is not found, None is returned.
    */
    pub fn get_index(&self, tab_body: Entity) -> Option<usize> {
        for i in 0..self.tabs.len() {
            let (_, body) = self.tabs[i];
            if body == tab_body {
                return Some(i);
            }
        }
        return None;
    }

    /**
    Visually refresh the current tab. This is used when, for example, the selected tab is removed,
    so the tab that take it's place need to be visually updated.
    */
    fn refresh_selected_tab(&mut self, ctx: &mut Context) {
        let tab = self.tabs[self.selected];
        ctx.get_widget(tab.0).set("selected", true);
        ctx.get_widget(tab.1).set("visibility", Visibility::Visible);
    }

    /**
    Change the selected tab by index. Unlike the public "select_by_index", this happen immediatly.
    */
    fn select_by_index_internal(&mut self, ctx: &mut Context, mut index: usize) {
        //No tabs could be selected if there are no one, so return immediatly
        if self.tabs.len() == 0 {
            return;
        }

        //If the passed index is greater than tab count, select the last one
        if index >= self.tabs.len() && index != 0 {
            index = self.tabs.len() - 1;
        }

        if self.selected != index {
            let current_tab = self.tabs[self.selected];
            let new_tab = self.tabs[index];

            //Toggle current button, the new button is toggled by user click
            ctx.get_widget(current_tab.0).set("selected", false);

            //Hide current body
            ctx.get_widget(current_tab.1)
                .set("visibility", Visibility::Hidden);

            //The new tab is not "selected" because it is already done by the user click

            //Show new body
            ctx.get_widget(new_tab.1)
                .set("visibility", Visibility::Visible);

            self.selected = index;
        }
    }

    ///Add a new tab to the widget. Unlike the public "add_tab", this happen immediatly.
    fn add_tab_internal(&mut self, ctx: &mut Context, header_text: String, body: Entity) {
        //Create the new tab
        let header = self.create_tab_header(ctx, header_text, body);

        //Set tab body hidden
        ctx.get_widget(body).set("visibility", Visibility::Hidden);

        //Push button to the header container
        ctx.append_child_entity_to(header, self.header_container);

        //Push the body to the body container
        ctx.append_child_entity_to(body, self.body_container);

        //Push the new tab to the list
        self.tabs.push((header, body));

        //If the added tab is the first
        if self.tabs.len() == 1 {
            //Select the tab just inserted
            self.selected = 0;
            self.refresh_selected_tab(ctx);
        }
    }

    ///Remove a tab from the widget. Unlike the public "remove_tab", this happen immediatly.
    fn remove_tab_internal(&mut self, ctx: &mut Context, body: Entity) {
        match self.get_index(body) {
            Some(index) => {
                //Pop the index tab out of the stored tabs
                let (header, body) = self.tabs.remove(index);

                //Push button to the header container
                ctx.remove_child_from(header, self.header_container);

                //Push the body to the body container
                ctx.remove_child_from(body, self.body_container);

                //If there is at least one tab
                if self.tabs.len() != 0 {
                    //If selected is greater than tab count, select the last one
                    if self.selected >= self.tabs.len() {
                        self.selected = self.tabs.len() - 1;
                    }

                    //Only update current selection if the removed tab is lesser than the selected.
                    //If it is greater, there is no need to update, but simply remove the target tab
                    if index <= self.selected {
                        self.refresh_selected_tab(ctx);
                    }
                }
            }
            None => (),
        }
    }

    /**
    Set the visibility of the close button on all tabs. Unlike the public "set_close_button_visibility", this happen immediatly.
    If the passed "value" is equal to "self.close_button_visibility", so the requested visibility is already present, nothing happen.
    */
    fn set_close_button_visibility_internal(&mut self, ctx: &mut Context, value: bool) {
        if self.close_button_visibility != value {
            self.close_button_visibility = value;
            let new_visibility = if self.close_button_visibility {
                Visibility::Visible
            } else {
                Visibility::Collapsed
            };
            for tab in &self.tabs {
                ctx.get_widget(tab.0).set("close_button", new_visibility);
            }
        }
    }

    //Create a new TabHeader entity and return it. For internal use.
    fn create_tab_header(&self, ctx: &mut Context, text: String, body: Entity) -> Entity {
        let cloned_entity = ctx.entity;
        TabHeader::new()
            .visibility(if self.close_button_visibility {
                Visibility::Visible
            } else {
                Visibility::Collapsed
            })
            .text(String16::from(text))
            .on_header_click(move |states, _| {
                states
                    .get_mut::<TabWidgetState>(cloned_entity)
                    .select_by_body(body);
                true
            })
            .on_close_click(move |states, _| {
                states
                    .get_mut::<TabWidgetState>(cloned_entity)
                    .remove_by_body(body);
                true
            })
            .build(&mut ctx.build_context())
    }
}

impl State for TabWidgetState {
    fn init(&mut self, _: &mut Registry, ctx: &mut Context) {
        self.header_container = ctx.child(HEADER_CONTAINER).entity();
        self.body_container = ctx.child(BODY_CONTAINER).entity();
    }
    fn update(&mut self, _: &mut Registry, ctx: &mut Context) {
        let actions: Vec<TabWidgetAction> = self.actions.drain(..).collect();
        for action in actions {
            match action {
                TabWidgetAction::SelectByIndex(index) => {
                    self.select_by_index_internal(ctx, index);
                }
                TabWidgetAction::SelectByBody(body) => {
                    if let Some(index) = self.get_index(body) {
                        self.select_by_index_internal(ctx, index)
                    }
                }
                TabWidgetAction::Add(header_text, body) => {
                    self.add_tab_internal(ctx, header_text, body);
                }
                TabWidgetAction::Remove(body) => {
                    self.remove_tab_internal(ctx, body);
                }
                TabWidgetAction::SetCloseButtonVisibility(value) => {
                    self.set_close_button_visibility_internal(ctx, value);
                }
            }
        }
    }
}

widget!(
    /**
    The `TabWidget` widget can store and control multiple tabs with arbitrary content. Only the selected tab will show it's content.

    This example creates a TabWidget:
    ```rust
    TabWidget::new()
    .tab("Tab header 1",TextBlock::new().text("Tab content 1").build(ctx))
    .tab("Tab header 2",TextBlock::new().text("Tab content 2").build(ctx))
    .tab("Tab header 3",TextBlock::new().text("Tab content 3").build(ctx))
    .build(ctx)
     ```
     */
    TabWidget<TabWidgetState>: ChangedHandler
    {
        /// Sets or shares the visibility of the close button.
        //close_button: bool,
        /// Sets or shares the spacing between tabs.
        spacing: f64
    }
);

impl TabWidget {
    ///Set the close button visibility
    pub fn close_button(mut self, value: bool) -> Self {
        self.state
            .actions
            .push(TabWidgetAction::SetCloseButtonVisibility(value));
        self
    }
    ///Add a tab the widget
    pub fn tab<T: Into<String>>(mut self, header: T, body: Entity) -> Self {
        self.state
            .actions
            .push(TabWidgetAction::Add(header.into(), body));
        self
    }
}

impl Template for TabWidget {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        self.name("TabWidget").child(
            Grid::new()
                .rows(Rows::new().add(32).add("*"))
                .child(
                    Stack::new()
                        .id(HEADER_CONTAINER)
                        .orientation("horizontal")
                        .spacing(id)
                        .build(ctx),
                )
                .child(
                    Grid::new()
                        .attach(Grid::row(1))
                        .id(BODY_CONTAINER)
                        .build(ctx),
                )
                .build(ctx),
        )
    }
}
<commit_msg>Tab header does not properly display caused by setting the visibility of the wrong entity<commit_after>use crate::prelude::*;

// --- KEYS --
const HEADER_CONTAINER: &str = "header_container";
const BODY_CONTAINER: &str = "body_container";
// --- KEYS --

/**
The `TabHeaderState` is used to store some callbacks that will be applied during template function.
Once the template function is called, they are no more used.
*/
#[derive(Default, AsAny)]
pub struct TabHeaderState {
    //Callback called when user click on the header of the tab (normally used to switch to the clicked tab). Only used during initialization
    on_header_click_callback: Option<Box<dyn 'static + Fn(&mut StatesContext, Point) -> bool>>,
    //Callback called when user click on the close button near the tab header (normally used to close the tab). Only used during initialization
    on_close_click_callback: Option<Box<dyn 'static + Fn(&mut StatesContext, Point) -> bool>>,
}

impl State for TabHeaderState {}

widget!(
    /// The `TabHeader` widget is used internally to managed tabs headers. Not meant for other uses.
    TabHeader<TabHeaderState>: ChangedHandler
    {
        /// Sets or shares the background property.
        background: Brush,

        /// Sets or shares the border radius property.
        border_radius: f64,

        /// Sets or shares the border thickness property.
        border_width: Thickness,

        /// Sets or shares the border brush property.
        border_brush: Brush,

        /// Sets or shares the padding property.
        padding: Thickness,

        /// Sets or shares the foreground property.
        foreground: Brush,

        /// Sets or shares the text property.
        text: String16,

        /// Sets or share the font size property.
        font_size: f64,

        /// Sets or shares the font property.
        font: String,

        /// Sets or shares the icon property.
        icon: String,

        /// Sets or shares the icon brush property.
        icon_brush: Brush,

        /// Sets or share the icon font size property.
        icon_size: f64,

        /// Sets or shares the icon font property.
        icon_font: String,

        /// Sets or shares the selected property.
        selected: bool,

        /// Sets or shares the spacing between icon and text.
        spacing: f64,

        /// Sets or shares the close button visibility.
        close_button: Visibility
    }
);

impl TabHeader {
    ///Set the callback that is called when user click on the header (generally used to switch tab)
    pub fn on_header_click<T: 'static + Fn(&mut StatesContext, Point) -> bool>(
        mut self,
        callback: T,
    ) -> Self {
        self.state.on_header_click_callback = Some(Box::new(callback));
        self
    }

    ///Set the callback that is called when user click on the close button near the header (generally used to close the tab)
    pub fn on_close_click<T: 'static + Fn(&mut StatesContext, Point) -> bool>(
        mut self,
        callback: T,
    ) -> Self {
        self.state.on_close_click_callback = Some(Box::new(callback));
        self
    }
}

impl Template for TabHeader {
    fn template(mut self, id: Entity, ctx: &mut BuildContext) -> Self {
        let mut toggle_button = ToggleButton::new()
            .background(id)
            .border_radius(id)
            .border_width(id)
            .border_brush(id)
            .padding(id)
            .foreground(id)
            .text(id)
            .font_size(id)
            .font(id)
            .icon(id)
            .icon_brush(id)
            .icon_size(id)
            .icon_font(id)
            .selected(id)
            .spacing(id);

        if let Some(callback) = self.state.on_header_click_callback.take() {
            toggle_button = toggle_button.on_click(callback);
        }

        let mut button = Button::new()
            .background(id)
            .border_radius(id)
            .border_width(id)
            .border_brush(id)
            .padding(id)
            .foreground(id)
            .font_size(id)
            .font(id)
            .icon(id)
            .icon_brush(id)
            .icon_size(id)
            .icon_font(id)
            .spacing(id)
            .text("X")
            .width(2)
            .visibility(("close_button", id));

        if let Some(callback) = self.state.on_close_click_callback.take() {
            button = button.on_click(callback);
        }
        //if self.close_button() == false {button = button.visibility(Visibility::Collapsed);}

        self.name("TabWidget")
            .selected(false)
            .height(36)
            .min_width(64)
            .background(colors::LYNCH_COLOR)
            .border_radius(4)
            .border_width(0)
            .border_brush("transparent")
            .padding((16, 0, 16, 0))
            .foreground(colors::LINK_WATER_COLOR)
            .text("Unnamed Tab")
            .font_size(fonts::FONT_SIZE_12)
            .font("Roboto Regular")
            .icon("")
            .icon_font("Material Icons")
            .icon_size(fonts::ICON_FONT_SIZE_12)
            .icon_brush(colors::LINK_WATER_COLOR)
            .spacing(8)
            .close_button(Visibility::Visible)
            .child(
                Stack::new()
                    .orientation("horizontal")
                    .child(toggle_button.build(ctx))
                    .child(button.build(ctx))
                    .build(ctx),
            )
    }
}

///Used to internally
enum TabWidgetAction {
    SelectByIndex(usize),
    SelectByBody(Entity),
    Add(String, Entity),
    Remove(Entity),
    SetCloseButtonVisibility(bool),
}
/**
Through the TabWidgetState it is possible to control the behaviour of TabWidget.
Nearly every called function on TabWidgetState will not be executed immediatly, but they are instead stored and executed during the update phase,
in the same order they are submitted.
*/
#[derive(Default, AsAny)]
pub struct TabWidgetState {
    ///Store all the pending actions. During the update call they will be resolved
    actions: Vec<TabWidgetAction>,

    header_container: Entity,
    body_container: Entity,

    tabs: Vec<(Entity, Entity)>, //Header , Body
    selected: usize,

    close_button_visibility: bool,
}

impl TabWidgetState {
    /**
    Switch the selected tab with one with the passed index.
    If the index is greater than the tab count, the last one will be selected.
    */
    pub fn select_by_index(&mut self, index: usize) {
        self.actions.push(TabWidgetAction::SelectByIndex(index));
    }
    /**
    Switch the selected tab with one with the passed body.
    If the no such body is found among the present tabs, nothing happen.
    */
    pub fn select_by_body(&mut self, entity: Entity) {
        self.actions.push(TabWidgetAction::SelectByBody(entity));
    }

    /**
    Remove the tab with the passed body.
    If the no such body is found among the present tabs, nothing happen.
    */
    pub fn remove_by_body(&mut self, entity: Entity) {
        self.actions.push(TabWidgetAction::Remove(entity));
    }

    ///Add a new tab to the widget.
    pub fn add_tab<T: Into<String>>(&mut self, header: T, body: Entity) {
        self.actions.push(TabWidgetAction::Add(header.into(), body));

        //At this point the tab has not been added yet, so we can check if len is == 0
        if self.tabs.len() == 0 {
            self.select_by_index(0);
        }
    }

    ///Set the close button visibility of all the tabs.
    pub fn set_close_button_visibility(&mut self, value: bool) {
        self.actions
            .push(TabWidgetAction::SetCloseButtonVisibility(value));
    }
    ///Get the close button visibility status
    pub fn get_close_button_visibility(&self) -> bool {
        self.close_button_visibility
    }

    /**
    Get the tab index associated with the passed body.
    If it is not found, None is returned.
    */
    pub fn get_index(&self, tab_body: Entity) -> Option<usize> {
        for i in 0..self.tabs.len() {
            let (_, body) = self.tabs[i];
            if body == tab_body {
                return Some(i);
            }
        }
        return None;
    }

    /**
    Visually refresh the current tab. This is used when, for example, the selected tab is removed,
    so the tab that take it's place need to be visually updated.
    */
    fn refresh_selected_tab(&mut self, ctx: &mut Context) {
        let tab = self.tabs[self.selected];
        ctx.get_widget(tab.0).set("selected", true);
        ctx.get_widget(tab.1).set("visibility", Visibility::Visible);
    }

    /**
    Change the selected tab by index. Unlike the public "select_by_index", this happen immediatly.
    */
    fn select_by_index_internal(&mut self, ctx: &mut Context, mut index: usize) {
        //No tabs could be selected if there are no one, so return immediatly
        if self.tabs.len() == 0 {
            return;
        }

        //If the passed index is greater than tab count, select the last one
        if index >= self.tabs.len() && index != 0 {
            index = self.tabs.len() - 1;
        }

        if self.selected != index {
            let current_tab = self.tabs[self.selected];
            let new_tab = self.tabs[index];

            //Toggle current button, the new button is toggled by user click
            ctx.get_widget(current_tab.0).set("selected", false);

            //Hide current body
            ctx.get_widget(current_tab.1)
                .set("visibility", Visibility::Hidden);

            //The new tab is not "selected" because it is already done by the user click

            //Show new body
            ctx.get_widget(new_tab.1)
                .set("visibility", Visibility::Visible);

            self.selected = index;
        }
    }

    ///Add a new tab to the widget. Unlike the public "add_tab", this happen immediatly.
    fn add_tab_internal(&mut self, ctx: &mut Context, header_text: String, body: Entity) {
        //Create the new tab
        let header = self.create_tab_header(ctx, header_text, body);

        //Set tab body hidden
        ctx.get_widget(body).set("visibility", Visibility::Hidden);

        //Push button to the header container
        ctx.append_child_entity_to(header, self.header_container);

        //Push the body to the body container
        ctx.append_child_entity_to(body, self.body_container);

        //Push the new tab to the list
        self.tabs.push((header, body));

        //If the added tab is the first
        if self.tabs.len() == 1 {
            //Select the tab just inserted
            self.selected = 0;
            self.refresh_selected_tab(ctx);
        }
    }

    ///Remove a tab from the widget. Unlike the public "remove_tab", this happen immediatly.
    fn remove_tab_internal(&mut self, ctx: &mut Context, body: Entity) {
        match self.get_index(body) {
            Some(index) => {
                //Pop the index tab out of the stored tabs
                let (header, body) = self.tabs.remove(index);

                //Push button to the header container
                ctx.remove_child_from(header, self.header_container);

                //Push the body to the body container
                ctx.remove_child_from(body, self.body_container);

                //If there is at least one tab
                if self.tabs.len() != 0 {
                    //If selected is greater than tab count, select the last one
                    if self.selected >= self.tabs.len() {
                        self.selected = self.tabs.len() - 1;
                    }

                    //Only update current selection if the removed tab is lesser than the selected.
                    //If it is greater, there is no need to update, but simply remove the target tab
                    if index <= self.selected {
                        self.refresh_selected_tab(ctx);
                    }
                }
            }
            None => (),
        }
    }

    /**
    Set the visibility of the close button on all tabs. Unlike the public "set_close_button_visibility", this happen immediatly.
    If the passed "value" is equal to "self.close_button_visibility", so the requested visibility is already present, nothing happen.
    */
    fn set_close_button_visibility_internal(&mut self, ctx: &mut Context, value: bool) {
        if self.close_button_visibility != value {
            self.close_button_visibility = value;
            let new_visibility = if self.close_button_visibility {
                Visibility::Visible
            } else {
                Visibility::Collapsed
            };
            for tab in &self.tabs {
                ctx.get_widget(tab.0).set("close_button", new_visibility);
            }
        }
    }

    //Create a new TabHeader entity and return it. For internal use.
    fn create_tab_header(&self, ctx: &mut Context, text: String, body: Entity) -> Entity {
        let cloned_entity = ctx.entity;
        TabHeader::new()
            .close_button(if self.close_button_visibility {
                Visibility::Visible
            } else {
                Visibility::Collapsed
            })
            .text(String16::from(text))
            .on_header_click(move |states, _| {
                states
                    .get_mut::<TabWidgetState>(cloned_entity)
                    .select_by_body(body);
                true
            })
            .on_close_click(move |states, _| {
                states
                    .get_mut::<TabWidgetState>(cloned_entity)
                    .remove_by_body(body);
                true
            })
            .build(&mut ctx.build_context())
    }
}

impl State for TabWidgetState {
    fn init(&mut self, _: &mut Registry, ctx: &mut Context) {
        self.header_container = ctx.child(HEADER_CONTAINER).entity();
        self.body_container = ctx.child(BODY_CONTAINER).entity();
    }
    fn update(&mut self, _: &mut Registry, ctx: &mut Context) {
        let actions: Vec<TabWidgetAction> = self.actions.drain(..).collect();
        for action in actions {
            match action {
                TabWidgetAction::SelectByIndex(index) => {
                    self.select_by_index_internal(ctx, index);
                }
                TabWidgetAction::SelectByBody(body) => {
                    if let Some(index) = self.get_index(body) {
                        self.select_by_index_internal(ctx, index)
                    }
                }
                TabWidgetAction::Add(header_text, body) => {
                    self.add_tab_internal(ctx, header_text, body);
                }
                TabWidgetAction::Remove(body) => {
                    self.remove_tab_internal(ctx, body);
                }
                TabWidgetAction::SetCloseButtonVisibility(value) => {
                    self.set_close_button_visibility_internal(ctx, value);
                }
            }
        }
    }
}

widget!(
    /**
    The `TabWidget` widget can store and control multiple tabs with arbitrary content. Only the selected tab will show it's content.

    This example creates a TabWidget:
    ```rust
    TabWidget::new()
    .tab("Tab header 1",TextBlock::new().text("Tab content 1").build(ctx))
    .tab("Tab header 2",TextBlock::new().text("Tab content 2").build(ctx))
    .tab("Tab header 3",TextBlock::new().text("Tab content 3").build(ctx))
    .build(ctx)
     ```
     */
    TabWidget<TabWidgetState>: ChangedHandler
    {
        /// Sets or shares the spacing between tabs.
        spacing: f64
    }
);

impl TabWidget {
    ///Set the close button visibility
    pub fn close_button(mut self, value: bool) -> Self {
        self.state
            .actions
            .push(TabWidgetAction::SetCloseButtonVisibility(value));
        self
    }
    ///Add a tab the widget
    pub fn tab<T: Into<String>>(mut self, header: T, body: Entity) -> Self {
        self.state
            .actions
            .push(TabWidgetAction::Add(header.into(), body));
        self
    }
}

impl Template for TabWidget {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        self.name("TabWidget")
        .close_button(true)
        .child(
            Grid::new()
                .rows(Rows::new().add(32).add("*"))
                .child(
                    Stack::new()
                        .id(HEADER_CONTAINER)
                        .orientation("horizontal")
                        .spacing(id)
                        .build(ctx),
                )
                .child(
                    Grid::new()
                        .attach(Grid::row(1))
                        .id(BODY_CONTAINER)
                        .build(ctx),
                )
                .build(ctx),
        )
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Partial is similar to Option where `Value` replaces `Some` and `Nothing` replaces `None`.
//!
//! `Fake` means that we got a value to pass for continuation (e.g. in `map` or `and_then`) but without real meaning, so it's an error to unwrap it.
//!
//! Value transformation are only from Value to Fake to Nothing which means that a Fake value will never be a Value again.
//! Use case: When compiling, an error in one function must be reported but should
//! not prevent the compilation of a second function to detect more errors in one run.
//! This intermediate state is represented by `Fake`.

use monad::partial::Partial::*;

#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub enum Partial<T>
{
  Value(T),
  Fake(T),
  Nothing
}

impl<T> Partial<T>
{
  pub fn unwrap(self) -> T {
    match self {
      Value(x) => x,
      Fake(_) => panic!("called `Partial::unwrap()` on a `Fake` value"),
      Nothing => panic!("called `Partial::unwrap()` on a `Nothing` value")
    }
  }

  pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Partial<U> {
    match self {
      Value(x) => Value(f(x)),
      Fake(x) => Fake(f(x)),
      Nothing => Nothing
    }
  }

  pub fn and_then<U, F: FnOnce(T) -> Partial<U>>(self, f: F) -> Partial<U> {
    match self {
      Value(x) => f(x),
      Fake(x) => match f(x) {
        Value(x) => Fake(x),
        x => x
      },
      Nothing => Nothing
    }
  }
}

#[test]
fn partial() {
  assert_eq!(Value(9i32).unwrap(), 9i32);
  assert_eq!(Value(9i32).map(|i|i*2), Value(18i32));
  assert_eq!(Fake(9i32).map(|i|i*2), Fake(18i32));
  assert_eq!(Nothing.map(|i:i32|i), Nothing);
  assert_eq!(Value(9i32).and_then(|i| Value(i*2)), Value(18i32));
  assert_eq!(Value(9i32).and_then(|i| Fake(i*2)), Fake(18i32));
  assert_eq!(Fake(9i32).and_then(|i| Fake(i*2)), Fake(18i32));
  // Even if you return a Value, it automatically coerces to Fake.
  assert_eq!(Fake(9i32).and_then(|i| Value(i*2)), Fake(18i32));
  assert_eq!(Fake(9i32).and_then(|_| -> Partial<i32> { Nothing }), Nothing);
}
<commit_msg>[Partial] Add several new methods for manipulating a partial structure.<commit_after>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Partial is similar to Option where `Value` replaces `Some` and `Nothing` replaces `None`.
//!
//! `Fake` means that we got a value to pass for continuation (e.g. in `map` or `and_then`) but without real meaning, so it's an error to unwrap it.
//!
//! Value transformation are only from Value to Fake to Nothing which means that a Fake value will never be a Value again.
//! Use case: When compiling, an error in one function must be reported but should
//! not prevent the compilation of a second function to detect more errors in one run.
//! This intermediate state is represented by `Fake`.

use monad::partial::Partial::*;

#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub enum Partial<T>
{
  Value(T),
  Fake(T),
  Nothing
}

impl<T> Partial<T>
{
  pub fn unwrap(self) -> T {
    match self {
      Value(x) => x,
      Fake(_) => panic!("called `Partial::unwrap()` on a `Fake` value"),
      Nothing => panic!("called `Partial::unwrap()` on a `Nothing` value")
    }
  }

  pub fn unwrap_or_else<F>(self, f: F) -> T where
   F: FnOnce() -> T
  {
    match self {
      Value(x) => x,
      _ => f()
    }
  }

  pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Partial<U> {
    match self {
      Value(x) => Value(f(x)),
      Fake(x) => Fake(f(x)),
      Nothing => Nothing
    }
  }

  pub fn and_then<U, F: FnOnce(T) -> Partial<U>>(self, f: F) -> Partial<U> {
    match self {
      Value(x) => f(x),
      Fake(x) => match f(x) {
        Value(x) => Fake(x),
        x => x
      },
      Nothing => Nothing
    }
  }

  pub fn and_next<U, F: FnOnce(T) -> Partial<U>>(self, f: F) -> Partial<U> {
    match self {
      Value(x) => f(x),
      _ => Nothing
    }
  }
}

fn nothing_i32(_: i32) -> Partial<i32> {
  Nothing
}

#[test]
fn partial_unwrap() {
  assert_eq!(Value(9i32).unwrap(), 9i32);
}

#[test]
#[should_panic]
fn partial_unwrap_fake() {
  Fake(9i32).unwrap();
}

#[test]
#[should_panic]
fn partial_unwrap_nothing() {
  let x: Partial<i32> = Nothing;
  x.unwrap();
}

#[test]
fn partial_unwrap_or_else() {
  assert_eq!(Value(9i32).unwrap_or_else(|| 1i32), 9i32);
  assert_eq!(Fake(9i32).unwrap_or_else(|| 1i32), 1i32);
  assert_eq!(Nothing.unwrap_or_else(|| 1i32), 1i32);
}

#[test]
fn partial_map() {
  assert_eq!(Value(9i32).map(|i|i*2), Value(18i32));
  assert_eq!(Fake(9i32).map(|i|i*2), Fake(18i32));
  assert_eq!(Nothing.map(|i:i32|i), Nothing);
}

#[test]
fn partial_and_then() {
  assert_eq!(Value(9i32).and_then(|i| Value(i*2)), Value(18i32));
  assert_eq!(Value(9i32).and_then(|i| Fake(i*2)), Fake(18i32));
  assert_eq!(Fake(9i32).and_then(|i| Fake(i*2)), Fake(18i32));
  // Even if you return a Value, it automatically coerces to Fake.
  assert_eq!(Fake(9i32).and_then(|i| Value(i*2)), Fake(18i32));
  assert_eq!(Fake(9i32).and_then(nothing_i32), Nothing);
}

#[test]
fn partial_and_next() {
  assert_eq!(Value(1i32).and_next(|i| Value(i*2)), Value(2));
  assert_eq!(Value(1i32).and_next(|i| Fake(i*2)), Fake(2));
  assert_eq!(Value(1i32).and_next(nothing_i32), Nothing);
  assert_eq!(Fake(1i32).and_next(|i| Value(i*2)), Nothing);
  assert_eq!(nothing_i32(0).and_next(|i| Value(i*2)), Nothing);
}
<|endoftext|>