sus-impls 0.2.1

Non-conflicting implementations for optional fields
Documentation
use sus_impls_macros::test_impls;

use sus_impls::Dependency;

fn test_expected<const N: usize, const M: usize>(
    field_names: [&'static str; N],
    input: &'static str,
    expected: [[Dependency; N]; M],
) {
    let expr: syn::Expr = syn::parse_str(input).unwrap();
    let impls = sus_impls::impls(&expr, &field_names).unwrap();

    assert_eq!(impls, expected);
}

#[test]
fn field() {
    test_impls!(["a"], "a", [[Set]]);
}

#[test]
fn any() {
    test_impls!(
        ["a", "b", "c"],
        "any(a, b, c)",
        [
            [Set, Generic, Generic],
            [Unset, Set, Generic],
            [Unset, Unset, Set],
        ]
    );
}

#[test]
fn all() {
    test_impls!(["a", "b", "c"], "all(a, b, c)", [[Set, Set, Set]]);
}

#[test]
fn mixed_any_all() {
    test_impls!(
        ["a", "b", "c"],
        "any(all(a, b), c)",
        [[Generic, Generic, Set], [Set, Set, Unset]]
    );
}

#[test]
fn any_of_two_same_length_all() {
    test_impls!(
        ["a", "b", "c", "d", "e", "f"],
        "any(all(a, b, c), all(d, e, f))",
        [
            [Set, Set, Set, Generic, Generic, Generic],
            [Unset, Generic, Generic, Set, Set, Set],
            [Set, Unset, Generic, Set, Set, Set],
            [Set, Set, Unset, Set, Set, Set],
        ]
    );
}

#[test]
fn any_of_three_same_length_all_with_one_intersecting_the_others() {
    test_impls!(
        ["a", "b", "c", "d"],
        "any(all(a, b), all(c, d), all(b, c))",
        [
            [Set, Set, Generic, Generic],
            [Unset, Generic, Set, Set],
            [Unset, Set, Set, Unset],
            [Set, Unset, Set, Set],
        ]
    );
}

#[test]
fn complicated0() {
    test_impls!(
        ["a", "b", "c", "d", "e", "f", "g"],
        "any(all(a, b, c, any(d, e)), all(b, f, any(a, g)))",
        [
            [Set, Set, Generic, Generic, Generic, Set, Generic],
            [Unset, Set, Generic, Generic, Generic, Set, Set],
            [Set, Set, Set, Set, Generic, Unset, Generic],
            [Set, Set, Set, Unset, Set, Unset, Generic],
        ]
    );
}

#[test]
fn all_of_two_same_length_anys0() {
    test_impls!(
        ["a", "b", "c", "d"],
        "all(any(a, b), any(c, d))",
        [
            [Set, Generic, Set, Generic],
            [Set, Generic, Unset, Set],
            [Unset, Set, Set, Generic],
            [Unset, Set, Unset, Set],
        ]
    );
}

#[test]
fn any_of_two_same_length_anys1() {
    test_impls!(
        ["a", "b", "c", "d", "e", "f"],
        "all(any(a, b, c), any(d, e, f))",
        [
            [Set, Generic, Generic, Set, Generic, Generic],
            [Set, Generic, Generic, Unset, Set, Generic],
            [Set, Generic, Generic, Unset, Unset, Set],
            [Unset, Set, Generic, Set, Generic, Generic],
            [Unset, Set, Generic, Unset, Set, Generic],
            [Unset, Set, Generic, Unset, Unset, Set],
            [Unset, Unset, Set, Set, Generic, Generic],
            [Unset, Unset, Set, Unset, Set, Generic],
            [Unset, Unset, Set, Unset, Unset, Set],
        ]
    );
}

#[test]
fn complicated1() {
    test_impls!(
        ["a", "b", "c", "d"],
        "any(all(a, c), all(a, d), all(b, d))",
        [
            [Set, Generic, Set, Generic],
            [Set, Generic, Unset, Set],
            [Unset, Set, Generic, Set],
        ]
    );
}

#[test]
fn new_impls_checked_as_lower_impls() {
    test_impls!(
        ["a", "b", "c", "d", "e"],
        "any(all(a, b), all(a, c), all(d, e))",
        [
            [Set, Set, Generic, Generic, Generic],
            [Set, Unset, Set, Generic, Generic],
            [Unset, Generic, Generic, Set, Set],
            [Set, Unset, Unset, Set, Set],
        ]
    );
}

#[test]
fn complicated2() {
    test_impls!(
        ["a", "b", "c", "d", "e", "f"],
        "any(all(any(a, b), any(c, d)), all(e, f))",
        [
            [Set, Generic, Set, Generic, Generic, Generic],
            [Set, Generic, Unset, Set, Generic, Generic],
            [Unset, Set, Set, Generic, Generic, Generic],
            [Unset, Set, Unset, Set, Generic, Generic],
            [Unset, Unset, Generic, Generic, Set, Set],
            [Set, Generic, Unset, Unset, Set, Set],
            [Unset, Set, Unset, Unset, Set, Set],
        ]
    );
}

#[test]
fn init_impls_conflict0() {
    test_impls!(
        ["a", "b", "c"],
        "any(all(a, c), all(not(a), b), all(b, c))",
        [[Unset, Set, Generic], [Set, Generic, Set],]
    );
}

#[test]
fn init_impls_conflict1() {
    test_impls!(
        ["a", "b", "c"],
        "any(a, all(not(a), b), all(b, c))",
        [[Unset, Set, Generic], [Set, Generic, Generic],]
    );
}

#[test]
fn complicated3() {
    test_impls!(
        ["a", "b", "c", "d"],
        "any(all(a, b), all(not(a), b), all(c, d))",
        [
            [Unset, Unset, Set, Set],
            [Unset, Set, Generic, Generic],
            [Set, Set, Generic, Generic],
            [Set, Unset, Set, Set],
        ]
    );
}

#[test]
fn complicated4() {
    test_impls!(
        ["a", "b", "c", "d"],
        "any(all(b, c), all(a, b), all(c, d))",
        [
            [Generic, Set, Set, Generic],
            [Set, Set, Unset, Generic],
            [Generic, Unset, Set, Set],
        ]
    );
}

#[test]
fn complicated5() {
    test_impls!(
        ["a", "b", "c", "d", "e", "f", "g", "h"],
        "any(all(a, b), all(b, c), all(b, d, e), all(f, g, h))",
        [
            [Set, Set, Generic, Generic, Generic, Generic, Generic, Generic],
            [Unset, Set, Set, Generic, Generic, Generic, Generic, Generic],
            [Unset, Set, Unset, Set, Set, Generic, Generic, Generic],
            [Unset, Unset, Generic, Generic, Generic, Set, Set, Set],
            [Set, Unset, Generic, Generic, Generic, Set, Set, Set],
            [Unset, Set, Unset, Unset, Generic, Set, Set, Set],
            [Unset, Set, Unset, Set, Unset, Set, Set, Set],
        ]
    );
}