Skip to main content

rpkl_jdx/
lib.rs

1use pkl::Deserializer;
2use pkl::PklSerialize;
3
4pub mod api;
5mod context;
6pub mod error;
7mod internal;
8pub mod pkl;
9mod utils;
10pub mod value;
11
12pub use error::{Error, Result};
13
14pub use api::evaluator::EvaluatorOptions;
15use utils::macros::_trace;
16pub use value::PklValue as Value;
17
18/// Evaluates a `.pkl` file and deserializes it as `T`. If you need to pass options to the evaluator, such as properties, use [`from_config_with_options`].
19///
20/// `path`: The path to the `.pkl` file
21///
22/// # Example
23///
24/// ```ignore
25/// ip = "127.0.0.1"
26/// database {
27///     username = "root"
28///     password = "password"
29/// }
30/// ```
31/// -------------
32/// ```no_run
33///
34/// use serde::Deserialize;
35///
36/// #[derive(Deserialize)]
37/// struct Config {
38///     ip: String,
39///     database: Database,
40/// }
41///
42/// #[derive(Deserialize)]
43/// struct Database {
44///     username: String,
45///     password: String,
46/// }
47///
48/// # fn main() -> Result<(), rpkl::Error> {
49/// let config: Config = rpkl::from_config("config.pkl")?;
50/// #    Ok(())
51/// # }
52/// ```
53pub fn from_config<T>(path: impl AsRef<std::path::Path>) -> Result<T>
54where
55    T: Sized + for<'de> serde::Deserialize<'de>,
56{
57    return from_config_with_options(path, EvaluatorOptions::default());
58}
59
60/// Allows for passing options to the evaluator, such as properties (e.g. `read("prop:username")`). See [`EvaluatorOptions`] for more information.
61///
62/// # Example
63///
64/// ```ignore
65/// ip = "127.0.0.1"
66/// credentials {
67///     username = read("prop:username")
68///     password = read("prop:password")
69/// }
70/// ```
71/// -------------
72/// ```no_run
73///
74/// use serde::Deserialize;
75/// use rpkl::api::evaluator::EvaluatorOptions;
76///
77/// #[derive(Deserialize)]
78/// struct Config {
79///     ip: String,
80///     database: Credentials,
81/// }
82///
83/// #[derive(Deserialize)]
84/// struct Credentials {
85///     username: String,
86///     password: String,
87/// }
88///
89/// # fn main() -> Result<(), rpkl::Error> {
90/// let options = EvaluatorOptions::default()
91///     .properties([("username", "root"), ("password", "password123")]);
92/// let config: Config = rpkl::from_config("config.pkl")?;
93/// #    Ok(())
94/// # }
95/// ```
96pub fn from_config_with_options<T>(
97    path: impl AsRef<std::path::Path>,
98    options: EvaluatorOptions,
99) -> Result<T>
100where
101    T: Sized + for<'de> serde::Deserialize<'de>,
102{
103    #[cfg(feature = "trace")]
104    {
105        use tracing::Level;
106        use tracing_subscriber::FmtSubscriber;
107
108        let subscriber = tracing_subscriber::FmtSubscriber::builder()
109            .with_max_level(Level::TRACE)
110            .finish();
111        tracing::subscriber::set_global_default(subscriber)
112            .expect("setting default subscriber failed");
113    }
114
115    let mut evaluator = api::Evaluator::new_from_options(options)?;
116    let pkl_mod = evaluator.evaluate_module(path.as_ref().to_path_buf())?;
117
118    let mut pkld = pkl_mod.serialize_pkl_ast()?;
119
120    _trace!("serialized pkl data {:?}", pkld);
121
122    T::deserialize(&mut Deserializer::from_pkl_map(&mut pkld))
123        .map_err(|e| Error::DeserializeError(format!("{}", e)))
124}