Skip to main content

hocon/
value.rs

1use indexmap::IndexMap;
2
3/// Payload for an unresolved substitution placeholder. Used internally by the
4/// deferred-resolution path (E12). Not part of the stable public API — marked
5/// `#[doc(hidden)]` to exclude from rustdoc and signal non-stable visibility.
6/// The type is `pub` for technical reasons (it is a field of the public `HoconValue`
7/// enum), but no semver guarantees are made for it.
8#[doc(hidden)]
9#[derive(Debug, Clone, PartialEq)]
10pub struct PlaceholderValue {
11    /// The dot-separated substitution path (e.g. `"db.host"`).
12    pub(crate) path: String,
13    /// Whether this was an optional substitution (`${?x}` vs `${x}`).
14    pub(crate) optional: bool,
15}
16
17/// A resolved HOCON value.
18///
19/// This is the tree that [`Config`](crate::Config) wraps. You normally interact
20/// with it through the typed getters on `Config`, but it is also returned
21/// directly by [`Config::get`](crate::Config::get) and
22/// [`Config::get_list`](crate::Config::get_list).
23#[non_exhaustive]
24#[derive(Debug, Clone, PartialEq)]
25pub enum HoconValue {
26    /// An ordered map of key-value pairs (HOCON object / JSON object).
27    Object(IndexMap<String, HoconValue>),
28    /// An ordered list of values (HOCON array / JSON array).
29    Array(Vec<HoconValue>),
30    /// A leaf value (string, number, boolean, or null).
31    Scalar(ScalarValue),
32    /// An unresolved substitution placeholder. Not part of the stable public API.
33    /// Marked `#[doc(hidden)]`; callers using the fused parse path will never see
34    /// this variant. May be encountered when `allow_unresolved=true` is passed to
35    /// [`Config::resolve`](crate::Config::resolve) — check `Config::is_resolved()`
36    /// instead of matching on this variant.
37    #[doc(hidden)]
38    Placeholder(PlaceholderValue),
39}
40
41/// The type tag for a scalar value.
42#[non_exhaustive]
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum ScalarType {
45    /// A string value.
46    String,
47    /// A numeric value (integer or floating-point).
48    Number,
49    /// A boolean value.
50    Boolean,
51    /// An explicit null.
52    Null,
53}
54
55/// A scalar (leaf) value inside a HOCON document.
56///
57/// Stores the raw string representation alongside a type tag.
58/// Typed access (i64, f64, bool) is done by parsing `raw` on demand.
59#[non_exhaustive]
60#[derive(Debug, Clone, PartialEq)]
61pub struct ScalarValue {
62    /// The raw string as it appeared in the source (or was produced by resolution).
63    pub raw: String,
64    /// The semantic type of this scalar.
65    pub value_type: ScalarType,
66}
67
68impl ScalarValue {
69    /// Create a new scalar value with explicit type.
70    pub fn new(raw: String, value_type: ScalarType) -> Self {
71        Self { raw, value_type }
72    }
73
74    /// Create a string-typed scalar.
75    pub fn string(raw: String) -> Self {
76        Self {
77            raw,
78            value_type: ScalarType::String,
79        }
80    }
81
82    /// Create a null scalar.
83    pub fn null() -> Self {
84        Self {
85            raw: "null".to_string(),
86            value_type: ScalarType::Null,
87        }
88    }
89
90    /// Create a boolean scalar.
91    pub fn boolean(value: bool) -> Self {
92        Self {
93            raw: if value { "true" } else { "false" }.to_string(),
94            value_type: ScalarType::Boolean,
95        }
96    }
97
98    /// Create a number scalar from a raw string.
99    pub fn number(raw: String) -> Self {
100        Self {
101            raw,
102            value_type: ScalarType::Number,
103        }
104    }
105}