moonbitstack/moonknob · @moonknob
A settings record, the flat arguments beside it, and the policy that
settles a disagreement. One package, and nothing outside the core library
to build it.
The order is this: what the library starts from, then the record, then
this call's argument. Wins picks the direction and
OnClash says what happens when the two disagree.
structClash
#derive(Eq, Debug)
pub(all) struct Clash[T] {
names : Array[String]
base : T
merged : T
}
| names : Array[String] | The settings that disagreed, in the order the function takes them. |
| base : T | What the function started from. |
| merged : T | The two laid together the way wins says. |
From the derive
pub fn[T : Eq] Clash::equal(Self[T], Self[T]) -> Bool
pub fn[T : Eq] Clash::not_equal(Self[T], Self[T]) -> Bool
pub fn[T : @debug.Debug] Clash::to_repr(Self[T]) -> @debug.Repr
typeMerge
Lays what a caller gave over what a function starts from, one setting at a time, and keeps the names of those that disagreed for settle.
test {
let merge = @moonknob.Merge::new(Extra)
let timeout = merge.pick("timeout", 30, Some(10))
assert_eq(timeout, 10)
assert_eq(merge.names().to_owned(), ["timeout"])
}
type Merge
fnMerge::names
pub fn Merge::names(self : Merge) -> ArrayView[String]
The names of the settings that disagreed so far.
fnMerge::new
pub fn Merge::new(wins : Wins) -> Merge
A merge that has recorded nothing yet and takes wins for every setting it is handed from here on.
fnMerge::pick
pub fn[V : Eq] Merge::pick(
self : Merge,
name : String,
base : V,
given : V?,
) -> V
One setting. given is None when the caller did not give it, and then base stands; a value equal to base stands without being a clash.
fnMerge::settle
pub fn[T] Merge::settle(
self : Merge,
clash : OnClash[T],
base : T,
merged : T,
site : String,
) -> T
clash applied to what was gathered: see [OnClash::settle].
fnMerge::union
pub fn[V : Eq] Merge::union(
self : Merge,
base : Map[String, V],
extra : Map[String, V],
) -> Map[String, V]
Two maps as one: every key of both, in the order base then extra has them, with wins deciding a key they both hold with different values.
enumOnClash
What to do when a setting is given twice with different values.
The same value given twice is not a clash: there is only one answer, and nothing is reported.
pub(all) enum OnClash[T] {
Ignore
Warn((String) -> Unit)
Panic
Handle((Clash[T]) -> T)
}
| Ignore | Take what wins says and say nothing. What most libraries do. |
| Warn((String) -> Unit) | Take what wins says and pass one line about it to the function, a
logger's warn for instance. The library itself prints nothing. |
| Panic | Abort, for where two answers are a mistake in the program rather than a
choice about configuration. |
| Handle((Clash[T]) -> T) | Pass the clash to the function and take what it returns. |
fnOnClash::settle
pub fn[T] OnClash::settle(
self : OnClash[T],
base : T,
merged : T,
names : Array[String],
site : String,
) -> T
What a function ends up with, given what it started from, the two laid together, and the settings that disagreed. With no names there was no clash, and merged comes back whatever self is.
site is the call and its two sources, for the warning and the abort: "jwt.verify: policy and arguments".
enumWins
#derive(Eq, Debug)
pub(all) enum Wins {
Base
Extra
}
| Base | What the function starts from: the record, or what it computes itself. |
From the derive
pub fn Wins::equal(Self, Self) -> Bool
pub fn Wins::not_equal(Self, Self) -> Bool
pub fn Wins::to_repr(Self) -> @debug.Repr