Rust bindings for the Pkl configuration language. Port of Apple's pkl-go.
Requires the
pklCLI. See pkl-lang.org to install.
cargo install --git https://github.com/DevYatsu/pkl_bindgen.git
pkl-bindgen eval config.pkl
pkl-bindgen expr 'name = "Hello, Pkl!"'
pkl-bindgen generate schema.pkl -o gen.rs[dependencies]
pkl_core = "0.2"
pkl_macros = "0.2"
tokio = { version = "1", features = ["rt", "macros"] }
[build-dependencies]
pkl_codegen = "0.2"Define a Pkl schema:
# config.pkl
host: String
port: UInt16
timeout: Duration?Two options to use it in Rust:
With codegen (recommended) — structs are auto-generated from your .pkl file. No manual struct definitions, no drift between schema and code:
// build.rs
fn main() { pkl_codegen::generate("config.pkl", "src/gen/config.rs").unwrap(); }// Just include — struct is auto-generated with correct types, optionals, etc.
include!("gen/config.rs");
let cfg: Root = CliEvaluator::new()
.evaluate(&ModuleSource::from_file("config.pkl")).await?;
println!("{}:{}", cfg.host, cfg.port);Without codegen — define structs manually with the derive macro:
#[derive(PklDecode)]
struct Config {
host: String,
port: u16,
timeout: Option<Duration>,
}
let cfg: Config = CliEvaluator::new()
.evaluate(&ModuleSource::from_file("config.pkl")).await?;// Simple (spawns pkl eval per call)
let e = CliEvaluator::new();
// Persistent server (10x faster repeated eval)
let e = ServerEvaluator::new().await?;
// Shared server process — multiple evaluators, one connection
let mgr = EvaluatorManager::new().await?;
let ev1 = mgr.new_evaluator().await?;
let ev2 = mgr.new_evaluator().await?;#[derive(PklDecode)]
struct Config {
name: String,
#[pkl(rename = "dbHost")] db_host: String,
#[pkl(default)] port: u16,
#[pkl(skip)] computed: String,
#[pkl(flatten)] extra: BTreeMap<String, Value>,
}
#[derive(PklDecode)]
enum Diet { Seeds, Berries, Insects }
#[derive(PklDecode)]
#[pkl(tag = "type")]
enum Shape {
Circle { radius: f64 },
#[pkl(tag = "rect")] Rect { width: f64, height: f64 },
}impl ResourceReader for MyReader {
fn scheme(&self) -> &str { "secret" }
fn read(&self, uri: &str) -> Result<Vec<u8>, String> { Ok(b"data".to_vec()) }
}
let e = ServerEvaluator::with_options(EvaluatorOptions {
resource_readers: vec![Box::new(MyReader)],
..Default::default()
}).await?;
// read("secret:key") → "data"Repo: github.com/DevYatsu/pkl_bindgen License: Apache 2.0