///|
/// Parse a `.env` string and optionally merge with an existing environment.
///
/// When `force` is `true`, parsed values overwrite existing keys in `env`.
/// When `false` (default), existing keys in `env` are preserved.
pub fn config(
src : String,
env? : Map[String, String] = Map([], capacity=0),
force? : Bool = false,
) -> Map[String, String] {
let parsed = parse(src)
merge(env, parsed, force~)
}
///|
/// Merge two maps. Keys from `other` are added to `base`.
/// When `force` is `true`, `other` wins on conflicts.
/// When `false`, `base` wins on conflicts.
pub fn merge(
base : Map[String, String],
other : Map[String, String],
force? : Bool = false,
) -> Map[String, String] {
let result = Map([], capacity=base.length() + other.length())
for k, v in base {
result[k] = v
}
for k, v in other {
if force || !result.contains(k) {
result[k] = v
}
}
result
}
///|
/// Parse multiple `.env` strings and merge them in order.
/// Later files override earlier ones.
pub fn load_multi(sources : Array[String]) -> Map[String, String] {
let result = Map([], capacity=16)
for src in sources {
let parsed = parse(src)
for k, v in parsed {
result[k] = v
}
}
result
}
///|
/// Like `load_multi`, but also merge with an existing environment.
/// When `force` is `true`, parsed values overwrite existing keys.
pub fn config_multi(
sources : Array[String],
env? : Map[String, String] = Map([], capacity=0),
force? : Bool = false,
) -> Map[String, String] {
let merged = load_multi(sources)
merge(env, merged, force~)
}
///|
/// Write parsed key-value pairs into a target map.
///
/// When `force` is `true`, parsed values overwrite existing keys.
/// When `false` (default), existing keys in `target` are preserved.
/// Returns the number of keys actually written.
pub fn populate(
target : Map[String, String],
parsed : Map[String, String],
force? : Bool = false,
) -> Int {
let mut count = 0
for k, v in parsed {
if force || !target.contains(k) {
target[k] = v
count += 1
}
}
count
}