Skip to main content

hocon/
options.rs

1// Copyright 2026 1o1 Co. Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8
9use std::collections::HashMap;
10use std::path::PathBuf;
11
12/// Options controlling the parse phase.
13///
14/// Construct via [`ParseOptions::defaults()`] and chain `with_*` methods.
15/// The struct literal `ParseOptions { .. }` is **not** a valid invocation —
16/// it would set `resolve_substitutions: false`, contradicting the Lightbend
17/// default of `true`. Per E12 §"Options encoding per language".
18#[derive(Debug, Clone)]
19pub struct ParseOptions {
20    /// Whether phase 2 (substitution resolution) runs immediately after parsing.
21    /// Default: `true` (Lightbend default — fused parse-and-resolve).
22    pub resolve_substitutions: bool,
23    /// User-visible source name for error messages when no file path is available.
24    /// Default: `None`.
25    pub origin_description: Option<String>,
26    /// Base directory for resolving relative include directives.
27    /// Default: `None` (current directory is used when building the internal opts).
28    pub(crate) base_dir: Option<PathBuf>,
29    /// Custom environment variable map.  When `None`, the process environment is
30    /// used (gated by `ResolveOptions::use_system_environment` at resolve time).
31    pub(crate) env: Option<HashMap<String, String>>,
32}
33
34impl ParseOptions {
35    /// Return `ParseOptions` with Lightbend-equivalent defaults:
36    /// `resolve_substitutions = true`, everything else `None`.
37    pub fn defaults() -> Self {
38        ParseOptions {
39            resolve_substitutions: true,
40            origin_description: None,
41            base_dir: None,
42            env: None,
43        }
44    }
45
46    /// Return a copy with `resolve_substitutions` set to `b`.
47    pub fn with_resolve_substitutions(mut self, b: bool) -> Self {
48        self.resolve_substitutions = b;
49        self
50    }
51
52    /// Return a copy with `origin_description` set to `s`.
53    pub fn with_origin_description(mut self, s: String) -> Self {
54        self.origin_description = Some(s);
55        self
56    }
57
58    /// Return a copy with `base_dir` set to `p`.
59    pub fn with_base_dir(mut self, p: PathBuf) -> Self {
60        self.base_dir = Some(p);
61        self
62    }
63
64    /// Return a copy with a custom `env` map (overrides process environment).
65    pub fn with_env(mut self, env: HashMap<String, String>) -> Self {
66        self.env = Some(env);
67        self
68    }
69}
70
71/// Options controlling the resolve phase.
72///
73/// Construct via [`ResolveOptions::defaults()`] and chain `with_*` methods.
74///
75/// **Distinct from the internal `resolver::InternalResolveOptions`** which
76/// also carries env / base_dir / include_stack for the resolver module.
77/// Translation from `ResolveOptions` to `InternalResolveOptions` happens
78/// at the `Config::resolve` boundary (T9).
79#[derive(Debug, Clone)]
80pub struct ResolveOptions {
81    /// When `true`, substitution paths not satisfied within the config tree
82    /// fall back to process environment variables. Default: `true`.
83    pub use_system_environment: bool,
84    /// When `true`, required-but-unsatisfied substitutions are left as
85    /// placeholders instead of returning a `ResolveError`. Default: `false`.
86    pub allow_unresolved: bool,
87}
88
89impl ResolveOptions {
90    /// Return `ResolveOptions` with Lightbend-equivalent defaults:
91    /// `use_system_environment = true`, `allow_unresolved = false`.
92    pub fn defaults() -> Self {
93        ResolveOptions {
94            use_system_environment: true,
95            allow_unresolved: false,
96        }
97    }
98
99    /// Return a copy with `use_system_environment` set to `b`.
100    pub fn with_use_system_environment(mut self, b: bool) -> Self {
101        self.use_system_environment = b;
102        self
103    }
104
105    /// Return a copy with `allow_unresolved` set to `b`.
106    pub fn with_allow_unresolved(mut self, b: bool) -> Self {
107        self.allow_unresolved = b;
108        self
109    }
110}