# kvf

A minimal, spec-compliant Rust parser library for [Kv Format 1.0](https://kvformat.org/).

## About Kv Format

Kv Format is a minimal key-value file format designed for simplicity and
correctness. This crate implements a parser fully compliant with the
[Kv Format 1.0 RC1 specification](https://kvformat.org/spec/1.0-rc1.html).

For full details on the format's syntax, error handling, and design rationale,
see [kvformat.org](https://kvformat.org/).

## Add to your project

```toml
[dependencies]
kvf = "0.1.0"
```

## Eager parsing

```rust
use kvf::{parse, Entry};

fn main() {
    let input = b"APP_NAME=My Application\nDEBUG=true\n";

    match parse(input) {
        Ok(entries) => {
            for entry in entries {
                if let Entry::Kv { key, value, .. } = entry {
                    println!("{key} = {value}");
                }
            }
        }
        Err(errors) => {
            for e in errors {
                eprintln!("Error: {e}");
            }
        }
    }
}
```

## Streaming parsing

```rust
use kvf::{parse_iter, Entry};

fn main() {
    let input = b"KEY=value\n# a comment\n";

    for result in parse_iter(input) {
        match result {
            Ok(Entry::Kv { key, value, line }) => {
                println!("line {line}: {key} = {value}");
            }
            Ok(Entry::Comment { text, line }) => {
                println!("line {line}: # {text}");
            }
            Err(e) => eprintln!("parse error: {e}"),
            _ => {}
        }
    }
}
```

## Custom configuration

```rust
use kvf::{parse_with_config, Entry, ParserConfig};

fn main() {
    let config = ParserConfig {
        emit_comments: false, // suppress comment entries
        emit_blanks: true,    // include blank-line entries
        emit_shebang: true,   // include the shebang entry (if present)
    };

    let input = b"#!/usr/bin/env kvf\n# ignored comment\nKEY=value\n\n";
    let entries = parse_with_config(input, &config).unwrap();

    for entry in &entries {
        println!("{entry:?}");
    }
}
```

## Error types

All errors implement `std::fmt::Display` and `std::error::Error`.
Error variants correspond to the error codes defined in
[Appendix B of the Kv Format 1.0 specification](https://kvformat.org/spec/1.0-rc1.html#appendix-b):

| Variant | Appendix B | Description |
|---|---|---|
| `BomError` | B.1 | Input starts with UTF-8 BOM (`EF BB BF`) |
| `InvalidUtf8Error { line }` | B.2 | Invalid UTF-8 byte sequence |
| `InvalidCharacterError { line }` | B.3 | Standalone CR or NUL character |
| `EmptyKeyError { line }` | B.4 | Line starts with `=` (empty key) |
| `MissingOperatorError { line }` | B.5 | Data line without `=` operator |
| `InvalidKeyError { line }` | B.6 | Key doesn't match `[A-Za-z_][A-Za-z0-9_]*` |
| `MissingFinalEolError` | B.7 | Final line not terminated by LF or CRLF |

## License

Licensed under either of <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>
or <a href="https://opensource.org/licenses/MIT">MIT license</a>, at your option.
