alef 0.114.0

Opinionated polyglot binding generator for Rust libraries
Documentation
use crate::e2e::fixture::Assertion;

#[derive(serde::Serialize)]
pub(super) struct Predicate {
    kind: String,
    expected: String,
    value_type: &'static str,
    values: Vec<String>,
}

pub(super) fn build(assertion: &Assertion) -> Option<Predicate> {
    let mut predicate = Predicate {
        kind: assertion.assertion_type.clone(),
        expected: String::new(),
        value_type: "",
        values: Vec::new(),
    };
    match assertion.assertion_type.as_str() {
        "not_empty" | "is_empty" => {}
        "contains_all" => {
            predicate.values = assertion
                .values
                .as_ref()?
                .iter()
                .map(|value| {
                    value.as_str()?;
                    Some(super::super::values::json_to_swift(value))
                })
                .collect::<Option<_>>()?;
        }
        "contains" => {
            let value = assertion.value.as_ref()?;
            value.as_str()?;
            predicate.expected = super::super::values::json_to_swift(value);
        }
        "count_min" | "count_equals" | "min_length" => {
            predicate.expected = assertion.value.as_ref()?.as_u64()?.to_string();
        }
        "equals" | "field_equals" | "greater_than" | "greater_than_or_equal" => {
            let value = assertion.value.as_ref()?;
            predicate.value_type = value_type(value)?;
            if !matches!(assertion.assertion_type.as_str(), "equals" | "field_equals") && !value.is_number() {
                return None;
            }
            predicate.expected = super::super::values::json_to_swift(value);
            if value.is_number() {
                set_number(&mut predicate, value);
            }
        }
        _ => return None,
    }
    Some(predicate)
}

fn set_number(predicate: &mut Predicate, value: &serde_json::Value) {
    predicate.expected = super::super::values::json_to_swift(&serde_json::Value::String(value.to_string()));
}

fn value_type(value: &serde_json::Value) -> Option<&'static str> {
    match value {
        serde_json::Value::String(_) => Some("String"),
        serde_json::Value::Bool(_) => Some("Bool"),
        serde_json::Value::Number(_) => Some("NSNumber"),
        _ => None,
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn numeric_predicates_preserve_signed_unsigned_and_float_domains() {
        for value in [
            serde_json::json!(i64::MIN),
            serde_json::json!(u64::MAX),
            serde_json::json!(1.25),
        ] {
            let expected = serde_json::to_string(&value.to_string()).unwrap();
            let predicate = super::build(&crate::e2e::fixture::Assertion {
                assertion_type: "equals".into(),
                value: Some(value),
                ..Default::default()
            })
            .unwrap();
            assert_eq!(predicate.value_type, "NSNumber");
            assert_eq!(predicate.expected, expected);
        }
    }
}