<commit_before>use context::Context;
use tera::Tera;

use super::NestedObject;

#[test]
fn render_macros() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        (
            "tpl",
            "{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}",
        ),
    ]).unwrap();

    let result = tera.render("tpl", &Context::new());

    assert_eq!(result.unwrap(), "Hello".to_string());
}

#[test]
fn render_macros_expression_arg() {
    let mut context = Context::new();
    context.insert("pages", &vec![1, 2, 3, 4, 5]);
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello(val)%}{{val}}{% endmacro hello %}"),
        ("tpl", "{% import \"macros\" as macros %}{{macros::hello(val=pages|last)}}"),
    ]).unwrap();

    let result = tera.render("tpl", &context);

    assert_eq!(result.unwrap(), "5".to_string());
}

#[test]
fn render_macros_in_child_templates_same_namespace() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("grandparent", "{% block hey %}hello{% endblock hey %}"),
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        ("macros2", "{% macro hi()%}Hi{% endmacro hi %}"),
        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}"),
        ("child", "{% extends \"parent\" %}{% import \"macros2\" as macros %}{% block hey %}{{super()}}/{{macros::hi()}}{% endblock hey %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "Hello/Hi".to_string());
}

#[test]
fn render_macros_in_child_templates_different_namespace() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("grandparent", "{% block hey %}hello{% endblock hey %}"),
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        ("macros2", "{% macro hi()%}Hi{% endmacro hi %}"),
        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}"),
        ("child", "{% extends \"parent\" %}{% import \"macros2\" as macros2 %}{% block hey %}{{super()}}/{{macros2::hi()}}{% endblock hey %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "Hello/Hi".to_string());
}

#[test]
fn render_macros_in_parent_template_with_inheritance() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        ("grandparent", "{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}"),
        ("child", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block hey %}{{super()}}/{{macros::hello()}}{% endblock hey %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "Hello/Hello".to_string());
}

#[test]
fn macro_param_arent_escaped() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros.html", r#"{% macro print(val) %}{{val|safe}}{% endmacro print %}"#),
        ("hello.html", r#"{% import "macros.html" as macros %}{{ macros::print(val=my_var)}}"#),
    ]).unwrap();
    let mut context = Context::new();
    context.insert("my_var", &"&");
    let result = tera.render("hello.html", &context);

    assert_eq!(result.unwrap(), "&".to_string());
}

#[test]
fn render_set_tag_macro() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        (
            "hello.html",
            "{% import \"macros\" as macros %}{% set my_var = macros::hello() %}{{my_var}}",
        ),
    ]).unwrap();
    let result = tera.render("hello.html", &Context::new());

    assert_eq!(result.unwrap(), "Hello".to_string());
}

#[test]
fn render_macros_with_default_args() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello(val=1) %}{{val}}{% endmacro hello %}"),
        ("hello.html", "{% import \"macros\" as macros %}{{macros::hello()}}"),
    ]).unwrap();
    let result = tera.render("hello.html", &Context::new());

    assert_eq!(result.unwrap(), "1".to_string());
}

#[test]
fn render_macros_override_default_args() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello(val=1) %}{{val}}{% endmacro hello %}"),
        ("hello.html", "{% import \"macros\" as macros %}{{macros::hello(val=2)}}"),
    ]).unwrap();
    let result = tera.render("hello.html", &Context::new());

    assert_eq!(result.unwrap(), "2".to_string());
}

#[test]
fn render_recursive_macro() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        (
            "macros",
            "{% macro factorial(n) %}{% if n > 1 %}{{ n }} - {{ self::factorial(n=n-1) }}{% else %}1{% endif %}{{ n }}{% endmacro factorial %}",
        ),
        ("hello.html", "{% import \"macros\" as macros %}{{macros::factorial(n=7)}}"),
    ]).unwrap();
    let result = tera.render("hello.html", &Context::new());

    assert_eq!(result.unwrap(), "7 - 6 - 5 - 4 - 3 - 2 - 11234567".to_string());
}

// https://github.com/Keats/tera/issues/202
#[test]
fn recursive_macro_with_loops() {
    let parent = NestedObject { label: "Parent".to_string(), parent: None, numbers: vec![1, 2, 3] };
    let child = NestedObject {
        label: "Child".to_string(),
        parent: Some(Box::new(parent)),
        numbers: vec![1, 2, 3],
    };
    let mut context = Context::new();
    context.insert("objects", &vec![child]);
    let mut tera = Tera::default();

    tera.add_raw_templates(vec![
        (
            "macros.html",
            r#"
{% macro label_for(obj, sep) -%}
  {%- if obj.parent -%}
    {{ self::label_for(obj=obj.parent, sep=sep) }}{{sep}}
  {%- endif -%}
  {{obj.label}}
  {%- for i in obj.numbers -%}{{ i }}{%- endfor -%}
{%- endmacro label_for %}
            "#,
        ),
        (
            "recursive",
            r#"
{%- import "macros.html" as macros -%}
{%- for obj in objects -%}
    {{ macros::label_for(obj=obj, sep="|") }}
{%- endfor -%}
"#,
        ),
    ]).unwrap();

    let result = tera.render("recursive", &context);

    assert_eq!(result.unwrap(), "Parent123|Child123".to_string());
}

// https://github.com/Keats/tera/issues/250
#[test]
fn render_macros_in_included() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro my_macro() %}my macro{% endmacro %}"),
        ("includeme", r#"{% import "macros" as macros %}{{ macros::my_macro() }}"#),
        ("example", r#"{% include "includeme" %}"#),
    ]).unwrap();
    let result = tera.render("example", &Context::new());

    assert_eq!(result.unwrap(), "my macro".to_string());
}

// https://github.com/Keats/tera/issues/255
#[test]
fn import_macros_into_other_macro_files() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("submacros", "{% macro test() %}Success!{% endmacro %}"),
        (
            "macros",
            r#"{% import "submacros" as sub %}{% macro test() %}{{ sub::test() }}{% endmacro %}"#,
        ),
        ("index", r#"{% import "macros" as macros %}{{ macros::test() }}"#),
    ]).unwrap();
    let result = tera.render("index", &Context::new());

    assert_eq!(result.unwrap(), "Success!".to_string());
}

#[test]
fn can_load_parent_macro_in_child() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}{{ 1 }}{% endmacro hello %}"),
        ("parent", "{% import \"macros\" as macros %}{{ macros::hello() }}{% block bob %}{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% block bob %}{{ super() }}Hey{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "1Hey".to_string());
}

#[test]
fn can_load_macro_in_child() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}{{ 1 }}{% endmacro hello %}"),
        ("parent", "{% block bob %}{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% import \"macros\" as macros %}{% block bob %}{{ macros::hello() }}{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "1".to_string());
}

// https://github.com/Keats/tera/issues/333
// this test fails in 0.11.14, worked in 0.11.10
#[test]
fn can_inherit_macro_import_from_parent() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}HELLO{% endmacro hello %}"),
        ("parent", "{% import \"macros\" as macros %}{% block bob %}parent{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% block bob %}{{macros::hello()}}{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::default());
    assert_eq!(result.unwrap(), "HELLO".to_string());
}

#[test]
fn can_inherit_macro_import_from_grandparent() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}HELLO{% endmacro hello %}"),
        ("grandparent", "{% import \"macros\" as macros %}{% block bob %}grandparent{% endblock bob %}"),
        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros2 %}{% block bob %}parent{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% block bob %}{{macros::hello()}}-{{macros2::hello()}}{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::default());
    assert_eq!(result.unwrap(), "HELLO-HELLO".to_string());
}

#[test]
fn can_load_macro_in_parent_with_grandparent() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}{{ 1 }}{% endmacro hello %}"),
        ("grandparent", "{% block bob %}{% endblock bob %}"),
        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block bob %}{{ macros::hello() }} - Hey{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% block bob %}{{ super() }}{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "1 - Hey".to_string());
}

#[test]
fn macro_can_load_macro_from_macro_files() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("submacros", "{% macro emma() %}Emma{% endmacro emma %}"),
        ("macros", "{% import \"submacros\" as submacros %}{% macro hommage() %}{{ submacros::emma() }} was an amazing person!{% endmacro hommage %}"),
        ("parent", "{% block main %}Someone was a terrible person!{% endblock main %} Don't you think?"),
        ("child", "{% extends \"parent\" %}{% import \"macros\" as macros %}{% block main %}{{ macros::hommage() }}{% endblock main %}")
    ]).unwrap();

    let result = tera.render("child", &Context::new());
    //println!("{:#?}", result);
    assert_eq!(result.unwrap(), "Emma was an amazing person! Don't you think?".to_string());
}
<commit_msg>Add tests for set_global in macros<commit_after>use context::Context;
use tera::Tera;

use super::NestedObject;

#[test]
fn render_macros() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        (
            "tpl",
            "{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}",
        ),
    ]).unwrap();

    let result = tera.render("tpl", &Context::new());

    assert_eq!(result.unwrap(), "Hello".to_string());
}

#[test]
fn render_macros_expression_arg() {
    let mut context = Context::new();
    context.insert("pages", &vec![1, 2, 3, 4, 5]);
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello(val)%}{{val}}{% endmacro hello %}"),
        ("tpl", "{% import \"macros\" as macros %}{{macros::hello(val=pages|last)}}"),
    ]).unwrap();

    let result = tera.render("tpl", &context);

    assert_eq!(result.unwrap(), "5".to_string());
}

#[test]
fn render_macros_in_child_templates_same_namespace() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("grandparent", "{% block hey %}hello{% endblock hey %}"),
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        ("macros2", "{% macro hi()%}Hi{% endmacro hi %}"),
        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}"),
        ("child", "{% extends \"parent\" %}{% import \"macros2\" as macros %}{% block hey %}{{super()}}/{{macros::hi()}}{% endblock hey %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "Hello/Hi".to_string());
}

#[test]
fn render_macros_in_child_templates_different_namespace() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("grandparent", "{% block hey %}hello{% endblock hey %}"),
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        ("macros2", "{% macro hi()%}Hi{% endmacro hi %}"),
        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}"),
        ("child", "{% extends \"parent\" %}{% import \"macros2\" as macros2 %}{% block hey %}{{super()}}/{{macros2::hi()}}{% endblock hey %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "Hello/Hi".to_string());
}

#[test]
fn render_macros_in_parent_template_with_inheritance() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        ("grandparent", "{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}"),
        ("child", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block hey %}{{super()}}/{{macros::hello()}}{% endblock hey %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "Hello/Hello".to_string());
}

#[test]
fn macro_param_arent_escaped() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros.html", r#"{% macro print(val) %}{{val|safe}}{% endmacro print %}"#),
        ("hello.html", r#"{% import "macros.html" as macros %}{{ macros::print(val=my_var)}}"#),
    ]).unwrap();
    let mut context = Context::new();
    context.insert("my_var", &"&");
    let result = tera.render("hello.html", &context);

    assert_eq!(result.unwrap(), "&".to_string());
}

#[test]
fn render_set_tag_macro() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
        (
            "hello.html",
            "{% import \"macros\" as macros %}{% set my_var = macros::hello() %}{{my_var}}",
        ),
    ]).unwrap();
    let result = tera.render("hello.html", &Context::new());

    assert_eq!(result.unwrap(), "Hello".to_string());
}

#[test]
fn render_macros_with_default_args() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello(val=1) %}{{val}}{% endmacro hello %}"),
        ("hello.html", "{% import \"macros\" as macros %}{{macros::hello()}}"),
    ]).unwrap();
    let result = tera.render("hello.html", &Context::new());

    assert_eq!(result.unwrap(), "1".to_string());
}

#[test]
fn render_macros_override_default_args() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello(val=1) %}{{val}}{% endmacro hello %}"),
        ("hello.html", "{% import \"macros\" as macros %}{{macros::hello(val=2)}}"),
    ]).unwrap();
    let result = tera.render("hello.html", &Context::new());

    assert_eq!(result.unwrap(), "2".to_string());
}

#[test]
fn render_recursive_macro() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        (
            "macros",
            "{% macro factorial(n) %}{% if n > 1 %}{{ n }} - {{ self::factorial(n=n-1) }}{% else %}1{% endif %}{{ n }}{% endmacro factorial %}",
        ),
        ("hello.html", "{% import \"macros\" as macros %}{{macros::factorial(n=7)}}"),
    ]).unwrap();
    let result = tera.render("hello.html", &Context::new());

    assert_eq!(result.unwrap(), "7 - 6 - 5 - 4 - 3 - 2 - 11234567".to_string());
}

// https://github.com/Keats/tera/issues/202
#[test]
fn recursive_macro_with_loops() {
    let parent = NestedObject { label: "Parent".to_string(), parent: None, numbers: vec![1, 2, 3] };
    let child = NestedObject {
        label: "Child".to_string(),
        parent: Some(Box::new(parent)),
        numbers: vec![1, 2, 3],
    };
    let mut context = Context::new();
    context.insert("objects", &vec![child]);
    let mut tera = Tera::default();

    tera.add_raw_templates(vec![
        (
            "macros.html",
            r#"
{% macro label_for(obj, sep) -%}
  {%- if obj.parent -%}
    {{ self::label_for(obj=obj.parent, sep=sep) }}{{sep}}
  {%- endif -%}
  {{obj.label}}
  {%- for i in obj.numbers -%}{{ i }}{%- endfor -%}
{%- endmacro label_for %}
            "#,
        ),
        (
            "recursive",
            r#"
{%- import "macros.html" as macros -%}
{%- for obj in objects -%}
    {{ macros::label_for(obj=obj, sep="|") }}
{%- endfor -%}
"#,
        ),
    ]).unwrap();

    let result = tera.render("recursive", &context);

    assert_eq!(result.unwrap(), "Parent123|Child123".to_string());
}

// https://github.com/Keats/tera/issues/250
#[test]
fn render_macros_in_included() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro my_macro() %}my macro{% endmacro %}"),
        ("includeme", r#"{% import "macros" as macros %}{{ macros::my_macro() }}"#),
        ("example", r#"{% include "includeme" %}"#),
    ]).unwrap();
    let result = tera.render("example", &Context::new());

    assert_eq!(result.unwrap(), "my macro".to_string());
}

// https://github.com/Keats/tera/issues/255
#[test]
fn import_macros_into_other_macro_files() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("submacros", "{% macro test() %}Success!{% endmacro %}"),
        (
            "macros",
            r#"{% import "submacros" as sub %}{% macro test() %}{{ sub::test() }}{% endmacro %}"#,
        ),
        ("index", r#"{% import "macros" as macros %}{{ macros::test() }}"#),
    ]).unwrap();
    let result = tera.render("index", &Context::new());

    assert_eq!(result.unwrap(), "Success!".to_string());
}

#[test]
fn can_load_parent_macro_in_child() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}{{ 1 }}{% endmacro hello %}"),
        ("parent", "{% import \"macros\" as macros %}{{ macros::hello() }}{% block bob %}{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% block bob %}{{ super() }}Hey{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "1Hey".to_string());
}

#[test]
fn can_load_macro_in_child() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}{{ 1 }}{% endmacro hello %}"),
        ("parent", "{% block bob %}{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% import \"macros\" as macros %}{% block bob %}{{ macros::hello() }}{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "1".to_string());
}

// https://github.com/Keats/tera/issues/333
// this test fails in 0.11.14, worked in 0.11.10
#[test]
fn can_inherit_macro_import_from_parent() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}HELLO{% endmacro hello %}"),
        ("parent", "{% import \"macros\" as macros %}{% block bob %}parent{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% block bob %}{{macros::hello()}}{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::default());
    assert_eq!(result.unwrap(), "HELLO".to_string());
}

#[test]
fn can_inherit_macro_import_from_grandparent() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}HELLO{% endmacro hello %}"),
        ("grandparent", "{% import \"macros\" as macros %}{% block bob %}grandparent{% endblock bob %}"),
        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros2 %}{% block bob %}parent{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% block bob %}{{macros::hello()}}-{{macros2::hello()}}{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::default());
    assert_eq!(result.unwrap(), "HELLO-HELLO".to_string());
}

#[test]
fn can_load_macro_in_parent_with_grandparent() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("macros", "{% macro hello()%}{{ 1 }}{% endmacro hello %}"),
        ("grandparent", "{% block bob %}{% endblock bob %}"),
        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block bob %}{{ macros::hello() }} - Hey{% endblock bob %}"),
        ("child", "{% extends \"parent\" %}{% block bob %}{{ super() }}{% endblock bob %}"),
    ]).unwrap();

    let result = tera.render("child", &Context::new());

    assert_eq!(result.unwrap(), "1 - Hey".to_string());
}

#[test]
fn macro_can_load_macro_from_macro_files() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("submacros", "{% macro emma() %}Emma{% endmacro emma %}"),
        ("macros", "{% import \"submacros\" as submacros %}{% macro hommage() %}{{ submacros::emma() }} was an amazing person!{% endmacro hommage %}"),
        ("parent", "{% block main %}Someone was a terrible person!{% endblock main %} Don't you think?"),
        ("child", "{% extends \"parent\" %}{% import \"macros\" as macros %}{% block main %}{{ macros::hommage() }}{% endblock main %}")
    ]).unwrap();

    let result = tera.render("child", &Context::new());
    //println!("{:#?}", result);
    assert_eq!(result.unwrap(), "Emma was an amazing person! Don't you think?".to_string());
}

#[test]
fn macro_can_access_global_context() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("parent", r#"{% import "macros" as macros %}{{ macros::test_global() }}"#),
        ("macros", r#"{% macro test_global() %}{% set_global value1 = "42" %}{% for i in range(end=1) %}{% set_global value2 = " is the truth." %}{% endfor %}{{ value1 }}{% endmacro test_global %}"#)
    ]).unwrap();

    let result = tera.render("parent", &Context::new());
    assert_eq!(result.unwrap(), "42".to_string());
}

#[test]
fn template_cant_access_macros_context() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("parent", r#"{% import "macros" as macros %}{{ macros::empty() }}{{ quote | default(value="I'd rather have roses on my table than diamonds on my neck.") }}"#),
        ("macros", r#"{% macro empty() %}{% set_global quote = "This should not reachable from the calling template!" %}{% endmacro empty %}"#)
    ]).unwrap();

    let result = tera.render("parent", &Context::new());
    assert_eq!(result.unwrap(), "I'd rather have roses on my table than diamonds on my neck.");
}

#[test]
fn parent_macro_cant_access_child_macro_context() {
    let mut tera = Tera::default();
    tera.add_raw_templates(vec![
        ("parent", "{% import \"macros\" as macros %}{{ macros::test_global() }}"),
        ("macros", r#"{% import "moremacros" as moremacros %}{% macro test_global() %}{% set_global value1 = "ACAB" %}{{ moremacros::another_one() }}{{ value1 }}-{{ value2 | default(value="ACAB") }}{% endmacro test_global %}"#),
        ("moremacros", r#"{% macro another_one() %}{% set_global value2 = "1312" %}{% endmacro another_one %}"#)
    ]).unwrap();

    let result = tera.render("parent", &Context::new());
    assert_eq!(result.unwrap(), "ACAB-ACAB".to_string());
}
<|endoftext|>


<commit_before>use super::super::{Grid, Y, X, Coord};
use grid_loop::{Edge, GridLoop, GridLoopField};
use super::*;

use rand::Rng;

#[derive(Debug, Clone, Copy)]
pub struct Symmetry {
    pub dyad: bool,         // 180-degree symmetry
    pub tetrad: bool,       // 90-degree symmetry
    pub horizontal: bool,   // horizontal line symmetry
    pub vertical: bool,     // vertical line symmetry
}

pub fn generate<R: Rng>(has_clue: &Grid<bool>, dic: &Dictionary, rng: &mut R) -> Option<Grid<Clue>> {
    let height = has_clue.height();
    let width = has_clue.width();
    let max_step = height * width * 10;

    let mut current_problem = Grid::new(height, width, NO_CLUE);
    let mut prev_score = 0;
    let temperature = 5.0f64;

    let mut unplaced_clues = 0;
    for y in 0..height {
        for x in 0..width {
            if has_clue[(Y(y), X(x))] {
                unplaced_clues += 1;
            }
        }
    }

    let mut last_field = Field::new(&current_problem, dic);

    for _ in 0..max_step {
        let mut pos_cand = vec![];
        for y in 0..height {
            for x in 0..width {
                let cd = (Y(y), X(x));
                if has_clue[cd] && (current_problem[cd] == NO_CLUE || has_undecided_nearby(&last_field, cd)) {
                    pos_cand.push(cd);
                }
            }
        }

        rng.shuffle(&mut pos_cand);

        let mut updated = false;
        for &pos in &pos_cand {
            let prev_clue = current_problem[pos];
            let is_zero_ok = !has_zero_nearby(&current_problem, pos);

            let mut new_clue_cand = vec![];
            for c in (if is_zero_ok { 0 } else { 1 })..4 {
                let c = Clue(c);
                if c != prev_clue {
                    new_clue_cand.push(c);
                }
            }

            rng.shuffle(&mut new_clue_cand);

            let mut common;
            if prev_clue == NO_CLUE {
                common = last_field.clone();
            } else {
                current_problem[pos] = NO_CLUE;
                common = Field::new(&current_problem, dic);
                common.check_all_cell();
            }

            for &c in &new_clue_cand {
                current_problem[pos] = c;

                let mut field = common.clone();
                field.add_clue(pos, c);

                if field.inconsistent() {
                    continue;
                }

                let current_score = field.grid_loop().num_decided_edges() - count_prohibited_patterns(has_clue, &field, &current_problem) * 10;

                if prev_score >= current_score {
                    if !(rng.next_f64() < ((current_score - prev_score) as f64 / temperature).exp()) {
                        continue;
                    }
                }

                let mut field_inout_test = field.clone();
                GridLoop::apply_inout_rule(&mut field_inout_test);
                GridLoop::check_connectability(&mut field_inout_test);
                if field_inout_test.inconsistent() {
                    continue;
                }

                updated = true;
                prev_score = current_score;
                if prev_clue == NO_CLUE {
                    unplaced_clues -= 1;
                }

                if field.fully_solved() && unplaced_clues == 0 {
                    return Some(current_problem);
                }

                last_field = field;
                break;
            }

            if updated {
                break;
            } else {
                current_problem[pos] = prev_clue;
            }
        }
    }

    None
}

fn has_undecided_nearby(field: &Field, clue_pos: Coord) -> bool {
    let (Y(y), X(x)) = clue_pos;
    let y = y * 2 + 1;
    let x = x * 2 + 1;

    let neighbor_size: i32 = 7;
    for dy in -neighbor_size..(neighbor_size + 1) {
        let dx_max = neighbor_size - dy.abs();
        for dx in -dx_max..(dx_max + 1) {
            let y2 = y + dy;
            let x2 = x + dx;

            let cd = (Y(y2), X(x2));
            if (dy & 1) != (dx & 1) {
                if field.get_edge_safe(cd) == Edge::Undecided {
                    return true;
                }
            }
        }
    }
    false
}

fn has_zero_nearby(problem: &Grid<Clue>, (Y(y), X(x)): Coord) -> bool {
    for dy in -1..2 {
        for dx in -1..2 {
            let cd = (Y(y + dy), X(x + dx));
            if problem.is_valid_coord(cd) && problem[cd] == Clue(0) {
                return true;
            }
        }
    }
    false
}
fn count_prohibited_patterns(has_clue: &Grid<bool>, field: &Field, problem: &Grid<Clue>) -> i32 {
    let neighbor = [
        (Y(1), X(0)),
        (Y(0), X(1)),
        (Y(-1), X(0)),
        (Y(0), X(-1)),
    ];
    let mut ret = 0;
    for y in 0..has_clue.height() {
        for x in 0..has_clue.width() {
            if has_clue[(Y(y), X(x))] && field.get_clue((Y(y), X(x))) == NO_CLUE && has_zero_nearby(problem, (Y(y), X(x))) {
                if
                    field.get_edge((Y(2 * y + 0), X(2 * x + 1))) == Edge::Blank &&
                    field.get_edge((Y(2 * y + 1), X(2 * x + 0))) == Edge::Blank &&
                    field.get_edge((Y(2 * y + 2), X(2 * x + 1))) == Edge::Blank &&
                    field.get_edge((Y(2 * y + 1), X(2 * x + 2))) == Edge::Blank {
                    ret += 1;
                    continue;
                }
            }
            if y > 0 && field.get_clue((Y(y - 1), X(x))) != NO_CLUE { continue; }
            if x > 0 && field.get_clue((Y(y), X(x - 1))) != NO_CLUE { continue; }
            if y < has_clue.height() - 1 && field.get_clue((Y(y + 1), X(x))) != NO_CLUE { continue; }
            if x < has_clue.width() - 1 && field.get_clue((Y(y), X(x + 1))) != NO_CLUE { continue; }

            if field.get_clue((Y(y), X(x))) == Clue(2) {
                if
                    field.get_edge_safe((Y(2 * y + 1 + 2), X(2 * x + 1 + 1))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 + 1), X(2 * x + 1 + 2))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 - 2), X(2 * x + 1 - 1))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 - 1), X(2 * x + 1 - 2))) == Edge::Blank {
                    ret += 1;
                    continue;
                }
                if
                    field.get_edge_safe((Y(2 * y + 1 - 2), X(2 * x + 1 + 1))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 - 1), X(2 * x + 1 + 2))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 + 2), X(2 * x + 1 - 1))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 + 1), X(2 * x + 1 - 2))) == Edge::Blank {
                    ret += 1;
                    continue;
                }
            } else if field.get_clue((Y(y), X(x))) == NO_CLUE {
                let mut n_in = 0;
                let mut n_blank = 0;

                for d in 0..4 {
                    let (Y(dy1), X(dx1)) = neighbor[d];
                    let (Y(dy2), X(dx2)) = neighbor[(d + 1) % 4];
                    let edge1 = field.get_edge_safe((Y(2 * y + 1 + dy1 * 2 + dy2), X(2 * x + 1 + dx1 * 2 + dx2)));
                    let edge2 = field.get_edge_safe((Y(2 * y + 1 + dy2 * 2 + dy1), X(2 * x + 1 + dx2 * 2 + dx1)));

                    match (edge1, edge2) {
                        (Edge::Blank, Edge::Blank) => n_blank += 1,
                        (Edge::Blank, Edge::Line) | (Edge::Line, Edge::Blank) => n_in += 1,
                        _ => (),
                    }
                }

                if n_in >= 1 && n_blank >= 2 {
                    ret += 1;
                }
            }
        }
    }
    ret
}

pub fn generate_placement<R: Rng>(height: i32, width: i32, num_clues: i32, symmetry: Symmetry, rng: &mut R) -> Grid<bool> {
    let mut num_clues = num_clues;
    let mut symmetry = symmetry;

    symmetry.dyad |= symmetry.tetrad;
    symmetry.tetrad &= (height == width);

    let mut grp_ids = Grid::new(height, width, false);
    let mut last_id = 0;

    let mut clue_positions: Vec<Vec<Coord>> = vec![];

    for y in 0..height {
        for x in 0..width {
            if !grp_ids[(Y(y), X(x))] {
                let mut sto = vec![];
                update_grp(y, x, last_id, symmetry, &mut grp_ids, &mut sto);
                clue_positions.push(sto);
            }
        }
    }

    let mut ret = Grid::new(height, width, false);
    while clue_positions.len() > 0 && num_clues > 0 {
        let mut scores = vec![];
        let mut scores_total = 0.0f64;

        for pos in &clue_positions {
            let (Y(y), X(x)) = pos[0];
            let mut score_base = 0.0f64;

            for dy in -2..3 {
                for dx in -2..3 {
                    let cd2 = (Y(y + dy), X(x + dx));
                    if ret.is_valid_coord(cd2) && ret[cd2] {
                        let dist = dy.abs() + dx.abs();
                        score_base += 5.0f64 - (dist as f64);
                        if dist == 1 {
                            score_base += 2.0f64;
                        }
                    }
                }
            }

            let pos_score = 64.0f64 * 2.0f64.powf((16.0f64 - score_base) / 2.0f64) + 4.0f64;
            scores.push(pos_score);
            scores_total += pos_score;
        }

        let mut thresh = rng.gen_range(0.0f64, scores_total);
        for i in 0..clue_positions.len() {
            if thresh < scores[i] {
                for &c in &(clue_positions[i]) {
                    ret[c] = true;
                    num_clues -= 1;
                }
                clue_positions.swap_remove(i);
                break;
            } else {
                thresh -= scores[i];
            }
        }
    }

    ret
}

fn update_grp(y: i32, x: i32, id: i32, symmetry: Symmetry, grp_ids: &mut Grid<bool>, sto: &mut Vec<Coord>) {
    if grp_ids[(Y(y), X(x))] {
        return;
    }
    grp_ids[(Y(y), X(x))] = true;
    sto.push((Y(y), X(x)));

    if symmetry.tetrad {
        update_grp(grp_ids.height() - 1 - x, y, id, symmetry, grp_ids, sto);
    } else if symmetry.dyad {
        update_grp(grp_ids.height() - 1 - y, grp_ids.width() - 1 - x, id, symmetry, grp_ids, sto);
    }
    if symmetry.horizontal {
        update_grp(grp_ids.height() - 1 - y, x, id, symmetry, grp_ids, sto);
    }
    if symmetry.vertical {
        update_grp(y, grp_ids.width() - 1 - x, id, symmetry, grp_ids, sto);
    }
}

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

    fn run_placement_test<R: Rng>(placement: Vec<Vec<bool>>, dic: &Dictionary, rng: &mut R) {
        let placement = ::common::vec_to_grid(&placement);
        let mut succeeded = false;

        for _ in 0..10 {
            let problem = generate(&placement, dic, rng);

            if let Some(problem) = problem {
                succeeded = true;

                assert_eq!(problem.height(), placement.height());
                assert_eq!(problem.width(), placement.width());

                for y in 0..placement.height() {
                    for x in 0..placement.width() {
                        let clue = problem[(Y(y), X(x))];
                        assert_eq!(placement[(Y(y), X(x))], clue != NO_CLUE);

                        if clue == Clue(0) {
                            for dy in -1..2 {
                                for dx in -1..2 {
                                    let y2 = y + dy;
                                    let x2 = x + dx;

                                    if 0 <= y2 && y2 < placement.height() && 0 <= x2 && x2 < placement.width() && (dy, dx) != (0, 0) {
                                        assert!(problem[(Y(y2), X(x2))] != Clue(0));
                                    }
                                }
                            }
                        }
                    }
                }

                let mut field = Field::new(&problem, &dic);
                field.check_all_cell();
                assert!(!field.inconsistent());
                assert!(field.fully_solved());

                break;
            }
        }

        assert!(succeeded);
    }

    #[test]
    fn test_generator() {
        let mut rng = rand::thread_rng();
        let dic = Dictionary::complete();

        run_placement_test(vec![
            vec![true , true , true , true , true ],
            vec![true , false, false, false, true ],
            vec![true , false, false, false, true ],
            vec![true , false, false, false, true ],
            vec![true , true , true , true , true ],
        ], &dic, &mut rng);

        run_placement_test(vec![
            vec![true , false, true , true , true ],
            vec![false, false, false, false, true ],
            vec![true , false, false, false, true ],
            vec![true , false, false, false, false],
            vec![true , true , true , false, true ],
        ], &dic, &mut rng);
    }
}
<commit_msg>Slitherlink: improve performance of generator using common fields more<commit_after>use super::super::{Grid, Y, X, Coord};
use grid_loop::{Edge, GridLoop, GridLoopField};
use super::*;

use rand::Rng;

#[derive(Debug, Clone, Copy)]
pub struct Symmetry {
    pub dyad: bool,         // 180-degree symmetry
    pub tetrad: bool,       // 90-degree symmetry
    pub horizontal: bool,   // horizontal line symmetry
    pub vertical: bool,     // vertical line symmetry
}

pub fn generate<R: Rng>(has_clue: &Grid<bool>, dic: &Dictionary, rng: &mut R) -> Option<Grid<Clue>> {
    let height = has_clue.height();
    let width = has_clue.width();
    let max_step = height * width * 10;

    let mut current_problem = Grid::new(height, width, NO_CLUE);
    let mut prev_score = 0;
    let temperature = 5.0f64;

    let mut unplaced_clues = 0;
    for y in 0..height {
        for x in 0..width {
            if has_clue[(Y(y), X(x))] {
                unplaced_clues += 1;
            }
        }
    }

    let mut last_field = Field::new(&current_problem, dic);

    for _ in 0..max_step {
        let mut pos_cand = vec![];
        for y in 0..height {
            for x in 0..width {
                let cd = (Y(y), X(x));
                if has_clue[cd] && (current_problem[cd] == NO_CLUE || has_undecided_nearby(&last_field, cd)) {
                    pos_cand.push(cd);
                }
            }
        }

        rng.shuffle(&mut pos_cand);

        let mut interpos_common = last_field.clone();
        let mut pos_with_clue = vec![];
        let mut pos_with_clue_idx = 0;

        for &pos in &pos_cand {
            if current_problem[pos] != NO_CLUE {
                pos_with_clue.push(pos);
            }
        }

        let mut updated = false;
        for &pos in &pos_cand {
            let prev_clue = current_problem[pos];
            let is_zero_ok = !has_zero_nearby(&current_problem, pos);

            let mut new_clue_cand = vec![];
            for c in (if is_zero_ok { 0 } else { 1 })..4 {
                let c = Clue(c);
                if c != prev_clue {
                    new_clue_cand.push(c);
                }
            }

            rng.shuffle(&mut new_clue_cand);

            let mut common;
            if prev_clue == NO_CLUE {
                common = last_field.clone();
            } else {
                if pos_with_clue_idx % 2 == 0 {
                    if pos_with_clue_idx == pos_with_clue.len() - 1 {
                        current_problem[pos] = NO_CLUE;
                        common = Field::new(&current_problem, dic);
                        common.check_all_cell();
                    } else {
                        let c1 = current_problem[pos_with_clue[pos_with_clue_idx]];
                        current_problem[pos_with_clue[pos_with_clue_idx]] = NO_CLUE;
                        let c2 = current_problem[pos_with_clue[pos_with_clue_idx + 1]];
                        current_problem[pos_with_clue[pos_with_clue_idx + 1]] = NO_CLUE;

                        interpos_common = Field::new(&current_problem, dic);
                        interpos_common.check_all_cell();

                        current_problem[pos_with_clue[pos_with_clue_idx]] = c1;
                        current_problem[pos_with_clue[pos_with_clue_idx + 1]] = c2;

                        common = interpos_common.clone();
                        common.add_clue(pos_with_clue[pos_with_clue_idx + 1], c2);
                    }
                } else {
                    common = interpos_common.clone();
                    common.add_clue(pos_with_clue[pos_with_clue_idx - 1], current_problem[pos_with_clue[pos_with_clue_idx - 1]]);
                }
                pos_with_clue_idx += 1;
            }

            for &c in &new_clue_cand {
                current_problem[pos] = c;

                let mut field = common.clone();
                field.add_clue(pos, c);

                if field.inconsistent() {
                    continue;
                }

                let current_score = field.grid_loop().num_decided_edges() - count_prohibited_patterns(has_clue, &field, &current_problem) * 10;

                if prev_score >= current_score {
                    if !(rng.next_f64() < ((current_score - prev_score) as f64 / temperature).exp()) {
                        continue;
                    }
                }

                let mut field_inout_test = field.clone();
                GridLoop::apply_inout_rule(&mut field_inout_test);
                GridLoop::check_connectability(&mut field_inout_test);
                if field_inout_test.inconsistent() {
                    continue;
                }

                updated = true;
                prev_score = current_score;
                if prev_clue == NO_CLUE {
                    unplaced_clues -= 1;
                }

                if field.fully_solved() && unplaced_clues == 0 {
                    return Some(current_problem);
                }

                last_field = field;
                break;
            }

            if updated {
                break;
            } else {
                current_problem[pos] = prev_clue;
            }
        }
    }

    None
}

fn has_undecided_nearby(field: &Field, clue_pos: Coord) -> bool {
    let (Y(y), X(x)) = clue_pos;
    let y = y * 2 + 1;
    let x = x * 2 + 1;

    let neighbor_size: i32 = 7;
    for dy in -neighbor_size..(neighbor_size + 1) {
        let dx_max = neighbor_size - dy.abs();
        for dx in -dx_max..(dx_max + 1) {
            let y2 = y + dy;
            let x2 = x + dx;

            let cd = (Y(y2), X(x2));
            if (dy & 1) != (dx & 1) {
                if field.get_edge_safe(cd) == Edge::Undecided {
                    return true;
                }
            }
        }
    }
    false
}

fn has_zero_nearby(problem: &Grid<Clue>, (Y(y), X(x)): Coord) -> bool {
    for dy in -1..2 {
        for dx in -1..2 {
            let cd = (Y(y + dy), X(x + dx));
            if problem.is_valid_coord(cd) && problem[cd] == Clue(0) {
                return true;
            }
        }
    }
    false
}
fn count_prohibited_patterns(has_clue: &Grid<bool>, field: &Field, problem: &Grid<Clue>) -> i32 {
    let neighbor = [
        (Y(1), X(0)),
        (Y(0), X(1)),
        (Y(-1), X(0)),
        (Y(0), X(-1)),
    ];
    let mut ret = 0;
    for y in 0..has_clue.height() {
        for x in 0..has_clue.width() {
            if has_clue[(Y(y), X(x))] && field.get_clue((Y(y), X(x))) == NO_CLUE && has_zero_nearby(problem, (Y(y), X(x))) {
                if
                    field.get_edge((Y(2 * y + 0), X(2 * x + 1))) == Edge::Blank &&
                    field.get_edge((Y(2 * y + 1), X(2 * x + 0))) == Edge::Blank &&
                    field.get_edge((Y(2 * y + 2), X(2 * x + 1))) == Edge::Blank &&
                    field.get_edge((Y(2 * y + 1), X(2 * x + 2))) == Edge::Blank {
                    ret += 1;
                    continue;
                }
            }
            if y > 0 && field.get_clue((Y(y - 1), X(x))) != NO_CLUE { continue; }
            if x > 0 && field.get_clue((Y(y), X(x - 1))) != NO_CLUE { continue; }
            if y < has_clue.height() - 1 && field.get_clue((Y(y + 1), X(x))) != NO_CLUE { continue; }
            if x < has_clue.width() - 1 && field.get_clue((Y(y), X(x + 1))) != NO_CLUE { continue; }

            if field.get_clue((Y(y), X(x))) == Clue(2) {
                if
                    field.get_edge_safe((Y(2 * y + 1 + 2), X(2 * x + 1 + 1))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 + 1), X(2 * x + 1 + 2))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 - 2), X(2 * x + 1 - 1))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 - 1), X(2 * x + 1 - 2))) == Edge::Blank {
                    ret += 1;
                    continue;
                }
                if
                    field.get_edge_safe((Y(2 * y + 1 - 2), X(2 * x + 1 + 1))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 - 1), X(2 * x + 1 + 2))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 + 2), X(2 * x + 1 - 1))) == Edge::Blank &&
                    field.get_edge_safe((Y(2 * y + 1 + 1), X(2 * x + 1 - 2))) == Edge::Blank {
                    ret += 1;
                    continue;
                }
            } else if field.get_clue((Y(y), X(x))) == NO_CLUE {
                let mut n_in = 0;
                let mut n_blank = 0;

                for d in 0..4 {
                    let (Y(dy1), X(dx1)) = neighbor[d];
                    let (Y(dy2), X(dx2)) = neighbor[(d + 1) % 4];
                    let edge1 = field.get_edge_safe((Y(2 * y + 1 + dy1 * 2 + dy2), X(2 * x + 1 + dx1 * 2 + dx2)));
                    let edge2 = field.get_edge_safe((Y(2 * y + 1 + dy2 * 2 + dy1), X(2 * x + 1 + dx2 * 2 + dx1)));

                    match (edge1, edge2) {
                        (Edge::Blank, Edge::Blank) => n_blank += 1,
                        (Edge::Blank, Edge::Line) | (Edge::Line, Edge::Blank) => n_in += 1,
                        _ => (),
                    }
                }

                if n_in >= 1 && n_blank >= 2 {
                    ret += 1;
                }
            }
        }
    }
    ret
}

pub fn generate_placement<R: Rng>(height: i32, width: i32, num_clues: i32, symmetry: Symmetry, rng: &mut R) -> Grid<bool> {
    let mut num_clues = num_clues;
    let mut symmetry = symmetry;

    symmetry.dyad |= symmetry.tetrad;
    symmetry.tetrad &= (height == width);

    let mut grp_ids = Grid::new(height, width, false);
    let mut last_id = 0;

    let mut clue_positions: Vec<Vec<Coord>> = vec![];

    for y in 0..height {
        for x in 0..width {
            if !grp_ids[(Y(y), X(x))] {
                let mut sto = vec![];
                update_grp(y, x, last_id, symmetry, &mut grp_ids, &mut sto);
                clue_positions.push(sto);
            }
        }
    }

    let mut ret = Grid::new(height, width, false);
    while clue_positions.len() > 0 && num_clues > 0 {
        let mut scores = vec![];
        let mut scores_total = 0.0f64;

        for pos in &clue_positions {
            let (Y(y), X(x)) = pos[0];
            let mut score_base = 0.0f64;

            for dy in -2..3 {
                for dx in -2..3 {
                    let cd2 = (Y(y + dy), X(x + dx));
                    if ret.is_valid_coord(cd2) && ret[cd2] {
                        let dist = dy.abs() + dx.abs();
                        score_base += 5.0f64 - (dist as f64);
                        if dist == 1 {
                            score_base += 2.0f64;
                        }
                    }
                }
            }

            let pos_score = 64.0f64 * 2.0f64.powf((16.0f64 - score_base) / 2.0f64) + 4.0f64;
            scores.push(pos_score);
            scores_total += pos_score;
        }

        let mut thresh = rng.gen_range(0.0f64, scores_total);
        for i in 0..clue_positions.len() {
            if thresh < scores[i] {
                for &c in &(clue_positions[i]) {
                    ret[c] = true;
                    num_clues -= 1;
                }
                clue_positions.swap_remove(i);
                break;
            } else {
                thresh -= scores[i];
            }
        }
    }

    ret
}

fn update_grp(y: i32, x: i32, id: i32, symmetry: Symmetry, grp_ids: &mut Grid<bool>, sto: &mut Vec<Coord>) {
    if grp_ids[(Y(y), X(x))] {
        return;
    }
    grp_ids[(Y(y), X(x))] = true;
    sto.push((Y(y), X(x)));

    if symmetry.tetrad {
        update_grp(grp_ids.height() - 1 - x, y, id, symmetry, grp_ids, sto);
    } else if symmetry.dyad {
        update_grp(grp_ids.height() - 1 - y, grp_ids.width() - 1 - x, id, symmetry, grp_ids, sto);
    }
    if symmetry.horizontal {
        update_grp(grp_ids.height() - 1 - y, x, id, symmetry, grp_ids, sto);
    }
    if symmetry.vertical {
        update_grp(y, grp_ids.width() - 1 - x, id, symmetry, grp_ids, sto);
    }
}

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

    fn run_placement_test<R: Rng>(placement: Vec<Vec<bool>>, dic: &Dictionary, rng: &mut R) {
        let placement = ::common::vec_to_grid(&placement);
        let mut succeeded = false;

        for _ in 0..10 {
            let problem = generate(&placement, dic, rng);

            if let Some(problem) = problem {
                succeeded = true;

                assert_eq!(problem.height(), placement.height());
                assert_eq!(problem.width(), placement.width());

                for y in 0..placement.height() {
                    for x in 0..placement.width() {
                        let clue = problem[(Y(y), X(x))];
                        assert_eq!(placement[(Y(y), X(x))], clue != NO_CLUE);

                        if clue == Clue(0) {
                            for dy in -1..2 {
                                for dx in -1..2 {
                                    let y2 = y + dy;
                                    let x2 = x + dx;

                                    if 0 <= y2 && y2 < placement.height() && 0 <= x2 && x2 < placement.width() && (dy, dx) != (0, 0) {
                                        assert!(problem[(Y(y2), X(x2))] != Clue(0));
                                    }
                                }
                            }
                        }
                    }
                }

                let mut field = Field::new(&problem, &dic);
                field.check_all_cell();
                assert!(!field.inconsistent());
                assert!(field.fully_solved());

                break;
            }
        }

        assert!(succeeded);
    }

    #[test]
    fn test_generator() {
        let mut rng = rand::thread_rng();
        let dic = Dictionary::complete();

        run_placement_test(vec![
            vec![true , true , true , true , true ],
            vec![true , false, false, false, true ],
            vec![true , false, false, false, true ],
            vec![true , false, false, false, true ],
            vec![true , true , true , true , true ],
        ], &dic, &mut rng);

        run_placement_test(vec![
            vec![true , false, true , true , true ],
            vec![false, false, false, false, true ],
            vec![true , false, false, false, true ],
            vec![true , false, false, false, false],
            vec![true , true , true , false, true ],
        ], &dic, &mut rng);
    }
}
<|endoftext|>


<commit_before>use bot::BotEnv;
use tasks::RunsTask;
use config::PresenceKind;

use serenity::prelude::Mutex;
use serenity::model::gateway::{Game, GameType};
use serenity::client::bridge::gateway::{ShardClientMessage, ShardRunnerMessage};
use serenity::client::bridge::gateway::ShardManager;

use chrono::Duration;

use rand::{Rng, thread_rng};

use std::sync::Arc;
use std::thread;

#[derive(Debug)]
pub struct RandomPresenceTask {
  next_sleep: i64,
  shard_manager: Arc<Mutex<ShardManager>>
}

impl RandomPresenceTask {
  pub fn new(shard_manager: Arc<Mutex<ShardManager>>) -> Self {
    RandomPresenceTask {
      next_sleep: 0,
      shard_manager
    }
  }
}

impl RunsTask for RandomPresenceTask {
  fn start(mut self, env: Arc<BotEnv>) {
    loop {
      if self.next_sleep == 0 {
        self.next_sleep = ::std::cmp::max(10, env.config.bot.presence.change_frequency);
      }
      thread::sleep(Duration::seconds(self.next_sleep).to_std().unwrap());
      info!("Changing presence");
      let game = match random_game(env.as_ref()) {
        Some(g) => g,
        None => {
          info!("No presence");
          continue;
        }
      };
      let manager = self.shard_manager.lock();
      let runners = manager.runners.lock();
      for si in runners.values() {
        let message = ShardClientMessage::Runner(ShardRunnerMessage::SetGame(Some(game.clone())));
        if let Err(e) = si.runner_tx.send(message) {
          warn!("Could not tell shard to change presence: {}", e);
        }
      }
      info!("Done changing presence");
    }
  }
}

pub fn random_game(env: &BotEnv) -> Option<Game> {
  let presence = match thread_rng().choose(&env.config.bot.presence.list) {
    Some(p) => p,
    None => return None
  };
  let game_type = match presence.kind {
    PresenceKind::Playing => GameType::Playing,
    PresenceKind::Streaming => GameType::Streaming,
    PresenceKind::Listening => GameType::Listening
  };
  Some(Game {
    kind: game_type,
    name: presence.content.clone(),
    url: presence.url.clone()
  })
}
<commit_msg>fix: use 12 seconds instead of 10<commit_after>use bot::BotEnv;
use tasks::RunsTask;
use config::PresenceKind;

use serenity::prelude::Mutex;
use serenity::model::gateway::{Game, GameType};
use serenity::client::bridge::gateway::{ShardClientMessage, ShardRunnerMessage};
use serenity::client::bridge::gateway::ShardManager;

use chrono::Duration;

use rand::{Rng, thread_rng};

use std::sync::Arc;
use std::thread;

#[derive(Debug)]
pub struct RandomPresenceTask {
  next_sleep: i64,
  shard_manager: Arc<Mutex<ShardManager>>
}

impl RandomPresenceTask {
  pub fn new(shard_manager: Arc<Mutex<ShardManager>>) -> Self {
    RandomPresenceTask {
      next_sleep: 0,
      shard_manager
    }
  }
}

impl RunsTask for RandomPresenceTask {
  fn start(mut self, env: Arc<BotEnv>) {
    loop {
      if self.next_sleep == 0 {
        self.next_sleep = ::std::cmp::max(12, env.config.bot.presence.change_frequency);
      }
      thread::sleep(Duration::seconds(self.next_sleep).to_std().unwrap());
      info!("Changing presence");
      let game = match random_game(env.as_ref()) {
        Some(g) => g,
        None => {
          info!("No presence");
          continue;
        }
      };
      let manager = self.shard_manager.lock();
      let runners = manager.runners.lock();
      for si in runners.values() {
        let message = ShardClientMessage::Runner(ShardRunnerMessage::SetGame(Some(game.clone())));
        if let Err(e) = si.runner_tx.send(message) {
          warn!("Could not tell shard to change presence: {}", e);
        }
      }
      info!("Done changing presence");
    }
  }
}

pub fn random_game(env: &BotEnv) -> Option<Game> {
  let presence = match thread_rng().choose(&env.config.bot.presence.list) {
    Some(p) => p,
    None => return None
  };
  let game_type = match presence.kind {
    PresenceKind::Playing => GameType::Playing,
    PresenceKind::Streaming => GameType::Streaming,
    PresenceKind::Listening => GameType::Listening
  };
  Some(Game {
    kind: game_type,
    name: presence.content.clone(),
    url: presence.url.clone()
  })
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
use hbs::{HandlebarsEngine, DirectorySource};
use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

/// Init Template renderer and add Tempaltes path.
/// It invoke to after middleware
pub fn template_render(paths: Vec<&str>) -> HandlebarsEngine {
    let mut template = HandlebarsEngine::new();

    // Add helpers
    template.register_helper("link", Box::new(link_helper));

    // add a directory source, all files with .html suffix
    // will be loaded as template
    for path in paths.iter() {
        template.add(Box::new(DirectorySource::new(path, ".html")));
    }

    // load templates from all registered sources
    if let Err(r) = template.reload() {
        panic!("{}", r);
    }
    template
}

fn link_helper(_: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let css_links = h.param(0).unwrap().value().as_array().unwrap();
    let mut css = "".to_owned();
    for link in css_links.iter() {
        css = format!("{}\t<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n", css, link);
    }
    try!(rc.writer.write(css.into_bytes().as_ref()));
    Ok(())
}<commit_msg>Render Helper - js link<commit_after>#![allow(dead_code)]
use hbs::{HandlebarsEngine, DirectorySource};
use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

/// Init Template renderer and add Tempaltes path.
/// It invoke to after middleware
pub fn template_render(paths: Vec<&str>) -> HandlebarsEngine {
    let mut template = HandlebarsEngine::new();

    // Add helpers
    template.register_helper("link", Box::new(link_helper));
    template.register_helper("script", Box::new(script_helper));

    // add a directory source, all files with .html suffix
    // will be loaded as template
    for path in paths.iter() {
        template.add(Box::new(DirectorySource::new(path, ".html")));
    }

    // load templates from all registered sources
    if let Err(r) = template.reload() {
        panic!("{}", r);
    }
    template
}

/// Css link Helper
/// usege: `{{#link ...}}`
fn link_helper(_: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let css_links = h.param(0).unwrap().value().as_array().unwrap();
    let mut css = "".to_owned();
    for link in css_links.iter() {
        css = format!("{}\t<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n", css, link);
    }
    try!(rc.writer.write(css.into_bytes().as_ref()));
    Ok(())
}

/// Js link Helper
/// usege: `{{#script ...}}`
fn script_helper(_: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let js_link = h.param(0).unwrap().value().as_string().unwrap();
    let js = format!("\t<script type=\"text/javascript\" charset=\"utf-8\" src=\"{}\"></script>\n", js_link);
    try!(rc.writer.write(js.into_bytes().as_ref()));
    Ok(())
}<|endoftext|>


<commit_before>//! Models about OAuth2 applications.

use std::fmt;

use bitflags::__impl_bitflags;
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};

use super::id::{snowflake, ApplicationId, UserId};
use super::{user::User, utils::*};
use crate::model::StdResult;

/// Information about a user's application. An application does not necessarily
/// have an associated bot user.
#[derive(Clone, Deserialize, Serialize)]
#[non_exhaustive]
pub struct ApplicationInfo {
    /// The bot user associated with the application. See [`BotApplication`] for
    /// more information.
    pub bot: Option<BotApplication>,
    /// Indicator of whether the bot is public.
    ///
    /// If a bot is public, anyone may invite it to their [`Guild`]. While a bot
    /// is private, only the owner may add it to a guild.
    ///
    /// [`Guild`]: super::guild::Guild
    #[serde(default = "default_true")]
    pub bot_public: bool,
    /// Indicator of whether the bot requires an OAuth2 code grant.
    pub bot_require_code_grant: bool,
    /// A description of the application, assigned by the application owner.
    pub description: String,
    /// A set of bitflags assigned to the application, which represent gated
    /// feature flags that have been enabled for the application.
    ///
    /// You can get a usable value from this by using [`ApplicationFlags::from_u64`]
    pub flags: Option<u64>,
    /// A hash pointing to the application's icon.
    ///
    /// This is not necessarily equivalent to the bot user's avatar.
    pub icon: Option<String>,
    /// The unique numeric Id of the application.
    pub id: ApplicationId,
    /// The name assigned to the application by the application owner.
    pub name: String,
    /// A list of redirect URIs assigned to the application.
    pub redirect_uris: Vec<String>,
    /// A list of RPC Origins assigned to the application.
    pub rpc_origins: Vec<String>,
    /// The application team group.
    pub team: Option<Vec<Team>>,
    /// The given secret to the application.
    ///
    /// This is not equivalent to the application's bot user's token.
    pub secret: String,
}

impl fmt::Debug for ApplicationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("ApplicationInfo")
            .field("bot", &self.bot)
            .field("bot_public", &self.bot_public)
            .field("bot_require_code_grant", &self.bot_require_code_grant)
            .field("description", &self.description)
            .field("flags", &self.flags)
            .field("icon", &self.icon)
            .field("id", &self.id)
            .field("name", &self.name)
            .field("redirect_uris", &self.redirect_uris)
            .field("rpc_origins", &self.rpc_origins)
            .field("team", &self.team)
            .finish()
    }
}

/// Information about an application with an application's bot user.
#[derive(Clone, Deserialize, Serialize)]
#[non_exhaustive]
pub struct BotApplication {
    /// The unique Id of the bot user.
    pub id: UserId,
    /// A hash of the avatar, if one is assigned.
    ///
    /// Can be used to generate a full URL to the avatar.
    pub avatar: Option<String>,
    /// Indicator of whether it is a bot.
    #[serde(default)]
    pub bot: bool,
    /// The discriminator assigned to the bot user.
    ///
    /// While discriminators are not unique, the `username#discriminator` pair
    /// is.
    pub discriminator: u16,
    /// The bot user's username.
    pub name: String,
    /// The token used to authenticate as the bot user.
    ///
    /// **Note**: Keep this information private, as untrusted sources can use it
    /// to perform any action with a bot user.
    pub token: String,
}

impl fmt::Debug for BotApplication {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BotApplication")
            .field("id", &self.id)
            .field("avatar", &self.avatar)
            .field("bot", &self.bot)
            .field("discriminator", &self.discriminator)
            .field("name", &self.name)
            .finish()
    }
}

/// Partial information about the given application.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PartialCurrentApplicationInfo {
    /// The unique Id of the user.
    pub id: ApplicationId,
    /// The flags associated with the application.
    ///
    /// You can get a usable value from this by using [`ApplicationFlags::from_u64`]
    pub flags: u64,
}

/// Information about the current application and its owner.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CurrentApplicationInfo {
    pub description: String,
    pub icon: Option<String>,
    pub id: ApplicationId,
    pub name: String,
    pub owner: User,
    #[serde(default)]
    pub rpc_origins: Vec<String>,
    pub bot_public: bool,
    pub bot_require_code_grant: bool,
    pub team: Option<Team>,
}

/// Information about the Team group of the application.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Team {
    /// The icon of the team.
    pub icon: Option<String>,
    /// The snowflake ID of the team.
    #[serde(with = "snowflake")]
    pub id: u64,
    /// The name of the team.
    pub name: String,
    /// The members of the team
    pub members: Vec<TeamMember>,
    /// The user id of the team owner.
    pub owner_user_id: UserId,
}

/// Information about a Member on a Team.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TeamMember {
    /// The member's membership state.
    pub membership_state: MembershipState,
    /// The list of permissions of the member on the team.
    ///
    /// NOTE: Will always be ["*"] for now.
    pub permissions: Vec<String>,
    /// The ID of the team they are a member of.
    #[serde(with = "snowflake")]
    pub team_id: u64,
    /// The user type of the team member.
    pub user: User,
}

#[derive(Clone, Debug, Copy, PartialEq)]
pub enum MembershipState {
    Invited = 1,
    Accepted = 2,
    Unknown = !0,
}

enum_number!(MembershipState {
    Invited,
    Accepted
});

/// The flags of the application.
#[derive(Clone)]
#[non_exhaustive]
pub struct ApplicationFlags {
    bits: u64,
}

impl ApplicationFlags {
    pub fn from_u64(bits: u64) -> Self {
        Self {
            bits,
        }
    }
}

__impl_bitflags! {
    ApplicationFlags: u64 {
        GATEWAY_PRESENCE = 1 << 12;
        GATEWAY_PRESENCE_LIMITED = 1 << 13;
        GATEWAY_GUILD_MEMBERS = 1 << 14;
        GATEWAY_GUILD_MEMBERS_LIMITED = 1 << 15;
        VERIFICATION_PENDING_GUILD_LIMIT = 2 << 16;
        EMBEDDED = 2 << 17;
        GATEWAY_MESSAGE_CONTENT = 2 << 18;
        GATEWAY_MESSAGE_CONTENT_LIMITED = 2 << 19;
    }
}

impl<'de> Deserialize<'de> for ApplicationFlags {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
        Ok(Self::from_bits_truncate(u64::deserialize(deserializer)?))
    }
}

impl Serialize for ApplicationFlags {
    fn serialize<S: Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
        serializer.serialize_u64(self.bits())
    }
}
<commit_msg>Use the internal `bitflags!` macro for `ApplicationFlags` (#1692)<commit_after>//! Models about OAuth2 applications.

use std::fmt;

use super::id::{snowflake, ApplicationId, UserId};
use super::{user::User, utils::*};

/// Information about a user's application. An application does not necessarily
/// have an associated bot user.
#[derive(Clone, Deserialize, Serialize)]
#[non_exhaustive]
pub struct ApplicationInfo {
    /// The bot user associated with the application. See [`BotApplication`] for
    /// more information.
    pub bot: Option<BotApplication>,
    /// Indicator of whether the bot is public.
    ///
    /// If a bot is public, anyone may invite it to their [`Guild`]. While a bot
    /// is private, only the owner may add it to a guild.
    ///
    /// [`Guild`]: super::guild::Guild
    #[serde(default = "default_true")]
    pub bot_public: bool,
    /// Indicator of whether the bot requires an OAuth2 code grant.
    pub bot_require_code_grant: bool,
    /// A description of the application, assigned by the application owner.
    pub description: String,
    /// A set of bitflags assigned to the application, which represent gated
    /// feature flags that have been enabled for the application.
    ///
    /// You can get a usable value from this by using [`ApplicationFlags::from_u64`]
    pub flags: Option<u64>,
    /// A hash pointing to the application's icon.
    ///
    /// This is not necessarily equivalent to the bot user's avatar.
    pub icon: Option<String>,
    /// The unique numeric Id of the application.
    pub id: ApplicationId,
    /// The name assigned to the application by the application owner.
    pub name: String,
    /// A list of redirect URIs assigned to the application.
    pub redirect_uris: Vec<String>,
    /// A list of RPC Origins assigned to the application.
    pub rpc_origins: Vec<String>,
    /// The application team group.
    pub team: Option<Vec<Team>>,
    /// The given secret to the application.
    ///
    /// This is not equivalent to the application's bot user's token.
    pub secret: String,
}

impl fmt::Debug for ApplicationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("ApplicationInfo")
            .field("bot", &self.bot)
            .field("bot_public", &self.bot_public)
            .field("bot_require_code_grant", &self.bot_require_code_grant)
            .field("description", &self.description)
            .field("flags", &self.flags)
            .field("icon", &self.icon)
            .field("id", &self.id)
            .field("name", &self.name)
            .field("redirect_uris", &self.redirect_uris)
            .field("rpc_origins", &self.rpc_origins)
            .field("team", &self.team)
            .finish()
    }
}

/// Information about an application with an application's bot user.
#[derive(Clone, Deserialize, Serialize)]
#[non_exhaustive]
pub struct BotApplication {
    /// The unique Id of the bot user.
    pub id: UserId,
    /// A hash of the avatar, if one is assigned.
    ///
    /// Can be used to generate a full URL to the avatar.
    pub avatar: Option<String>,
    /// Indicator of whether it is a bot.
    #[serde(default)]
    pub bot: bool,
    /// The discriminator assigned to the bot user.
    ///
    /// While discriminators are not unique, the `username#discriminator` pair
    /// is.
    pub discriminator: u16,
    /// The bot user's username.
    pub name: String,
    /// The token used to authenticate as the bot user.
    ///
    /// **Note**: Keep this information private, as untrusted sources can use it
    /// to perform any action with a bot user.
    pub token: String,
}

impl fmt::Debug for BotApplication {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BotApplication")
            .field("id", &self.id)
            .field("avatar", &self.avatar)
            .field("bot", &self.bot)
            .field("discriminator", &self.discriminator)
            .field("name", &self.name)
            .finish()
    }
}

/// Partial information about the given application.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PartialCurrentApplicationInfo {
    /// The unique Id of the user.
    pub id: ApplicationId,
    /// The flags associated with the application.
    ///
    /// You can get a usable value from this by using [`ApplicationFlags::from_u64`]
    pub flags: u64,
}

/// Information about the current application and its owner.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CurrentApplicationInfo {
    pub description: String,
    pub icon: Option<String>,
    pub id: ApplicationId,
    pub name: String,
    pub owner: User,
    #[serde(default)]
    pub rpc_origins: Vec<String>,
    pub bot_public: bool,
    pub bot_require_code_grant: bool,
    pub team: Option<Team>,
}

/// Information about the Team group of the application.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Team {
    /// The icon of the team.
    pub icon: Option<String>,
    /// The snowflake ID of the team.
    #[serde(with = "snowflake")]
    pub id: u64,
    /// The name of the team.
    pub name: String,
    /// The members of the team
    pub members: Vec<TeamMember>,
    /// The user id of the team owner.
    pub owner_user_id: UserId,
}

/// Information about a Member on a Team.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TeamMember {
    /// The member's membership state.
    pub membership_state: MembershipState,
    /// The list of permissions of the member on the team.
    ///
    /// NOTE: Will always be ["*"] for now.
    pub permissions: Vec<String>,
    /// The ID of the team they are a member of.
    #[serde(with = "snowflake")]
    pub team_id: u64,
    /// The user type of the team member.
    pub user: User,
}

#[derive(Clone, Debug, Copy, PartialEq)]
pub enum MembershipState {
    Invited = 1,
    Accepted = 2,
    Unknown = !0,
}

enum_number!(MembershipState {
    Invited,
    Accepted
});

bitflags! {
    /// The flags of the application.
    #[derive(Default)]
    pub struct ApplicationFlags: u64 {
        const GATEWAY_PRESENCE = 1 << 12;
        const GATEWAY_PRESENCE_LIMITED = 1 << 13;
        const GATEWAY_GUILD_MEMBERS = 1 << 14;
        const GATEWAY_GUILD_MEMBERS_LIMITED = 1 << 15;
        const VERIFICATION_PENDING_GUILD_LIMIT = 2 << 16;
        const EMBEDDED = 2 << 17;
        const GATEWAY_MESSAGE_CONTENT = 2 << 18;
        const GATEWAY_MESSAGE_CONTENT_LIMITED = 2 << 19;
    }
}

impl ApplicationFlags {
    pub fn from_u64(bits: u64) -> Self {
        Self {
            bits,
        }
    }
}
<|endoftext|>


<commit_before>use Renderable;
use Block;
use LiquidOptions;
use tags::RawBlock;
use lexer::Token;
use parser::parse;
use lexer::Element;
use lexer::Element::{Output, Tag, Raw};
use std::collections::HashMap;

struct RawT{
    content : String
}

impl Renderable for RawT{
    fn render(&self, context: &HashMap<String, String>) -> String{
        self.content.to_string()
    }
}

impl Block for RawBlock{
    fn initialize(&self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &LiquidOptions) -> Box<Renderable>{
        let content = tokens.iter().fold("".to_string(), |a, b|
                                         match b  {
                                            &Output(_, ref text) => text,
                                            &Tag(_, ref text) => text,
                                            &Raw(ref text) => text
                                         }.to_string() + a.to_string()
                                        );
        box RawT{content: content} as Box<Renderable>
    }
}
<commit_msg>Add raw test<commit_after>use Renderable;
use Block;
use LiquidOptions;
use tags::RawBlock;
use lexer::Token;
use parser::parse;
use lexer::Element;
use lexer::Element::{Output, Tag, Raw};
use std::collections::HashMap;

struct RawT{
    content : String
}

impl Renderable for RawT{
    fn render(&self, context: &HashMap<String, String>) -> String{
        self.content.to_string()
    }
}

impl Block for RawBlock{
    fn initialize(&self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &LiquidOptions) -> Box<Renderable>{
        let content = tokens.iter().fold("".to_string(), |a, b|
                                         match b  {
                                            &Output(_, ref text) => text,
                                            &Tag(_, ref text) => text,
                                            &Raw(ref text) => text
                                         }.to_string() + a.to_string()
                                        );
        box RawT{content: content} as Box<Renderable>
    }
}

#[test]
fn test_raw() {
    let block = RawBlock;
    let raw = block.initialize("raw", vec![][0..], vec![Output(vec![], "This is a test".to_string())], &LiquidOptions{blocks: HashMap::new(), tags: HashMap::new()});
    assert_eq!(raw.render(&HashMap::new()), "This is a test".to_string());
}
<|endoftext|>


<commit_before>use iron::prelude::*;
use iron::{BeforeMiddleware, Error};

use url::{Url, SchemeData};

// Errors for the win!
#[deriving(Show)]
pub struct MalformedRequest;
#[deriving(Show)]
pub struct NotFound;

impl Error for MalformedRequest
{
    fn name(&self) -> &'static str { "MalformedRequest" }
}

impl Error for NotFound
{
    fn name(&self) -> &'static str { "NoRoute" }
}

// The actual URLParser struct
pub struct URLParser;

impl URLParser
{

}

// Make URLParser a BeforeMiddleware
impl BeforeMiddleware for URLParser
{
    fn before(&self, req: &mut Request) -> IronResult<()>
    {
        // Currently do precisely nothing
        println!("{}", req);
        if(check_url(req))
        {
        	Ok(())
        }
        else
        {
        	Err(box MalformedRequest as IronError)
        }
    }
}

fn check_url(req: &mut Request) -> bool
{
	let parsed = Url::parse(req.url.to_string().as_slice()).ok().unwrap();
	println!("{}", parsed);
	let path = parsed.path();
	if((path.unwrap()[0] != "".to_string()) & (path.unwrap().len() != 1))
	{
		return false;
	}

	let mut found = false;
	let query = parsed.query_pairs().unwrap();

	for x in query.iter()
	{
		let r = "r".to_string();
		let val = match x
		{
			&(ref r, ref value) => { value },
			// (_, value) => {continue;},
		};

		if(!val.contains("/"))
		{
			return false;
		}
		else
		{
			found = true;
		}
	}

	if(found != true)
	{
		return false;
	}

	true
}
<commit_msg>Fixed an parsing error when the requested url is 'localhost/'<commit_after>use iron::prelude::*;
use iron::{BeforeMiddleware, Error};

use url::{Url, SchemeData};

// Errors for the win!
#[deriving(Show)]
pub struct MalformedRequest;
#[deriving(Show)]
pub struct NotFound;

impl Error for MalformedRequest
{
    fn name(&self) -> &'static str { "MalformedRequest" }
}

impl Error for NotFound
{
    fn name(&self) -> &'static str { "NoRoute" }
}

// The actual URLParser struct
pub struct URLParser;

impl URLParser
{

}

// Make URLParser a BeforeMiddleware
impl BeforeMiddleware for URLParser
{
    fn before(&self, req: &mut Request) -> IronResult<()>
    {
        // Currently do precisely nothing
        println!("{}", req);
        if(check_url(req))
        {
        	Ok(())
        }
        else
        {
        	Err(box MalformedRequest as IronError)
        }
    }
}

fn check_url(req: &mut Request) -> bool
{
	let parsed = Url::parse(req.url.to_string().as_slice()).ok().unwrap();
	let path = parsed.path();
	println!("{}\n{}", path, path.unwrap().len());
	if(path.unwrap()[0] != "".to_string() || path.unwrap().len() != 1)
	{
		return false;
	}

	let mut found = false;
    // This one returns an Option
    let mut query: Vec<(String, String)>;
    query = match parsed.query_pairs()
    {
        Some(query) => { query },
        None => { vec![("r".to_string(), "".to_string())] },
    };

	let get = String::from_str("r");

    for x in query.iter()
	{
		match x
		{
			&(ref get, ref value) =>
            {
                found = value.contains("/");
            },
			// &(_, _) => { false },
		};
	}
    return found;
}
<|endoftext|>