Open
Description
Hi, I'm considering using Starlark as a config file format - where you might normally use JSON or YAML or TOML via Serde.
So for example instead of a config file like
{
"servers": [
{
"name": "foo",
"url": "foo.example.com",
"port": 80
},
{
"name": "bar",
"url": "bar.example.com",
"port": 80
},
]
}
You could have
def server(name):
return {
"name": name,
"url": name + ".example.com",
"port": 80,
}
{
"servers": [server("foo"), server("bar")],
}
I got as far as this:
use std::path::Path;
use allocative::Allocative;
use starlark::any::ProvidesStaticType;
use starlark::environment::Globals;
use starlark::environment::Module;
use starlark::eval::Evaluator;
use starlark::syntax::AstModule;
use starlark::syntax::Dialect;
use starlark::values::starlark_value;
use starlark::values::NoSerialize;
use starlark::values::StarlarkValue;
use starlark::values::UnpackValue;
use anyhow::{anyhow, Result};
#[derive(
Debug,
derive_more::Display,
Allocative,
NoSerialize,
ProvidesStaticType,
UnpackValue,
)]
struct Config {
test: String,
}
#[starlark_value(type = "Config", UnpackValue, StarlarkTypeRepr)]
impl<'v> StarlarkValue<'v> for Config {}
pub fn read_config(path: &Path) -> Result<Config> {
let content = std::fs::read_to_string(path)?;
let file_name = path.file_name().ok_or(anyhow!("No file name in path"))?;
let file_name = file_name.to_str().ok_or(anyhow!("File name isn't valid UTF-8"))?;
read_config_text(content, file_name)
}
pub fn read_config_text(content: String, file_name: &str) -> Result<Config> {
let dialect = Dialect {
enable_f_strings: true,
..Dialect::Extended
};
let ast = AstModule::parse(file_name, content, &dialect).map_err(|e| anyhow!("Parse error: {e}"))?;
let globals = Globals::standard();
let module = Module::new();
let mut eval = Evaluator::new(&module);
let value = eval.eval_module(ast, &globals).map_err(|e| anyhow!("Eval error: {e}"))?;
UnpackValue::unpack_value_err(value)
}
Unfortunately #[derive(UnpackValue)]
apparently only works for enums. Is this kind of use case supported?
Metadata
Metadata
Assignees
Labels
No labels