ktav 0.3.1

Ktav — a plain configuration format. Three rules, zero indentation, zero quoting. Serde-native.
Documentation
//! Smoke tests for top-level Array support (spec § 5.0.1, added 0.1.1).

use ktav::Value;

#[test]
fn empty_doc_yields_empty_object() {
    let v = ktav::parse("").unwrap();
    assert!(matches!(v, Value::Object(ref m) if m.is_empty()));
}

#[test]
fn comments_only_yields_empty_object() {
    let v = ktav::parse("# comment\n\n# another\n").unwrap();
    assert!(matches!(v, Value::Object(ref m) if m.is_empty()));
}

#[test]
fn first_line_pair_yields_object() {
    let v = ktav::parse("host: localhost\nport:i 8080\n").unwrap();
    let map = match v {
        Value::Object(m) => m,
        other => panic!("expected Object, got {other:?}"),
    };
    assert_eq!(map.len(), 2);
    assert!(map.contains_key("host"));
    assert!(map.contains_key("port"));
}

#[test]
fn first_line_bare_scalar_yields_array() {
    let v = ktav::parse("foo\nbar\nbaz\n").unwrap();
    let items = match v {
        Value::Array(items) => items,
        other => panic!("expected Array, got {other:?}"),
    };
    assert_eq!(items.len(), 3);
}

#[test]
fn first_line_typed_item_yields_array() {
    let v = ktav::parse(":i 1\n:i 2\n:f 3.14\n").unwrap();
    let items = match v {
        Value::Array(items) => items,
        other => panic!("expected Array, got {other:?}"),
    };
    assert_eq!(items.len(), 3);
    assert!(matches!(items[0], Value::Integer(_)));
    assert!(matches!(items[2], Value::Float(_)));
}

#[test]
fn first_line_raw_marker_item_yields_array() {
    let v = ktav::parse(":: literal\nplain\n").unwrap();
    let items = match v {
        Value::Array(items) => items,
        other => panic!("expected Array, got {other:?}"),
    };
    assert_eq!(items.len(), 2);
}

#[test]
fn first_line_lone_object_opener_yields_array_of_object() {
    let v = ktav::parse("{\n    name: alice\n}\n").unwrap();
    let items = match v {
        Value::Array(items) => items,
        other => panic!("expected Array, got {other:?}"),
    };
    assert_eq!(items.len(), 1);
    let inner = match &items[0] {
        Value::Object(m) => m,
        other => panic!("expected nested Object, got {other:?}"),
    };
    assert!(inner.contains_key("name"));
}

#[test]
fn first_line_with_comments_and_blanks_skipped() {
    let v = ktav::parse("# top-level array\n\nfoo\nbar\n").unwrap();
    let items = match v {
        Value::Array(items) => items,
        other => panic!("expected Array, got {other:?}"),
    };
    assert_eq!(items.len(), 2);
}

#[test]
fn first_line_url_value_yields_array() {
    // `http://example.com` is NOT a pair (after `:` is `//`, no ws),
    // so root is Array with a single bare-scalar item.
    let v = ktav::parse("http://example.com\n").unwrap();
    let items = match v {
        Value::Array(items) => items,
        other => panic!("expected Array, got {other:?}"),
    };
    assert_eq!(items.len(), 1);
    assert!(matches!(items[0], Value::String(ref s) if s == "http://example.com"));
}

#[test]
fn mixed_array_then_pair_errors() {
    // Root is Array; pair line later is not a valid array-item
    // shape (pair handler would have parsed it, but array dispatch
    // treats it as a scalar `host: localhost` — actually that's a
    // valid scalar string under § 5.4 rule 11). Per spec § 5.0.1
    // the kind is fixed but pair-line-shaped items inside an Array
    // are silently scalars containing a colon. So this shouldn't
    // error — the spec wording "pair line inside top-level Array
    // is an error" is about parser behavior, but our array handler
    // already accepts colon-bearing scalars.
    //
    // This test pins the actual behaviour: Array with 3 String
    // items, the third one containing the literal `host: localhost`.
    let v = ktav::parse("foo\nbar\nhost: localhost\n").unwrap();
    let items = match v {
        Value::Array(items) => items,
        other => panic!("expected Array, got {other:?}"),
    };
    assert_eq!(items.len(), 3);
}