Expand description
Derive macro for parsing KEY=VALUE formats.
This crate provides Kv for automatically implementing parsers
for structs from KEY=VALUE formatted input.
§Field Types
| Rust Type | Attribute | Behavior |
|---|---|---|
T | Required single value | |
Option<T> | Optional single value | |
Vec<T> | Whitespace-separated values on single line | |
Option<Vec<T>> | Optional whitespace-separated values | |
Vec<T> | #[kv(multiline)] | Multiple lines collected into Vec |
Option<Vec<T>> | #[kv(multiline)] | Optional multiple lines |
HashMap<String, String> | #[kv(collect)] | Collects unhandled keys |
§Container Attributes
#[kv(allow_unknown)]- Ignore unknown keys instead of returning an error
§Field Attributes
#[kv(variable = "KEY")]- Use custom key name instead of uppercased field name#[kv(multiline)]- Collect multiple lines with the same key into aVec#[kv(collect)]- Collect all unhandled keys into thisHashMap<String, String>
§Duplicate Key Behavior
For non-multiline fields, duplicate keys overwrite the previous value.
For multiline fields, each occurrence appends to the Vec.
§Examples
use indoc::indoc;
use pkgsrc::kv::{KvError, Kv};
use pkgsrc::PkgName;
#[derive(Kv)]
pub struct Package {
pkgname: PkgName,
#[kv(variable = "SIZE_PKG")]
size: u64,
#[kv(multiline)]
description: Vec<String>,
homepage: Option<String>,
}
let input = indoc! {"
PKGNAME=foo-1.0
SIZE_PKG=1234
DESCRIPTION=A package that does
DESCRIPTION=many interesting things.
"};
let pkg = Package::parse(input)?;
assert_eq!(pkg.pkgname.pkgbase(), "foo");
assert_eq!(pkg.size, 1234);
assert_eq!(pkg.description, vec!["A package that does", "many interesting things."]);
assert_eq!(pkg.homepage, None);
// Missing required fields return an error.
assert!(Package::parse("PKGNAME=bar-1.0\n").is_err());Use collect to collect unhandled keys into a HashMap, for example
when parsing +BUILD_INFO where arbitrary variables will be present:
use indoc::indoc;
use std::collections::HashMap;
use pkgsrc::kv::{KvError, Kv};
#[derive(Kv)]
pub struct BuildInfo {
build_host: Option<String>,
machine_arch: Option<String>,
#[kv(collect)]
vars: HashMap<String, String>,
}
let input = indoc! {"
BUILD_DATE=2025-01-15 10:30:00 +0000
BUILD_HOST=builder.example.com
MACHINE_ARCH=x86_64
PKGPATH=devel/example
"};
let info = BuildInfo::parse(input)?;
assert_eq!(info.build_host, Some("builder.example.com".to_string()));
assert_eq!(info.machine_arch, Some("x86_64".to_string()));
assert_eq!(info.vars.get("PKGPATH"), Some(&"devel/example".to_string()));
assert_eq!(info.vars.get("VARBASE"), None);Derive Macros§
- Kv
- Derive macro for parsing
KEY=VALUEformatted input.