Current section
Files
Jump to
Current section
Files
src/scamper@config.erl
-module(scamper@config).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/scamper/config.gleam").
-export([new/1, add_transition/4, add_guarded_transition/5, set_final_states/2, set_on_enter/3, set_on_exit/3, set_on_transition/3, add_global_on_enter/2, add_global_on_exit/2, add_global_on_transition/2, add_invariant/2, set_event_policy/2, set_history_limit/2, set_history_snapshots/2, set_timeout/4, get_transitions/1, get_final_states/1, get_on_enter/1, get_on_exit/1, get_on_transition_state/1, get_global_on_enter/1, get_global_on_exit/1, get_global_on_transition/1, get_invariants/1, get_event_policy/1, get_history_limit/1, get_history_snapshots/1, get_timeouts/1, get_timestamp/1, get_timestamp_fn/1]).
-export_type([event_policy/0, transition_rule/3, config/3]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Configuration builder for scamper finite state machines.\n"
"\n"
" Build a config using the pipeline operator:\n"
"\n"
" ```gleam\n"
" config.new(timestamp_fn)\n"
" |> config.add_transition(from: Idle, on: Start, to: Running)\n"
" |> config.add_guarded_transition(from: Running, on: Complete, guard: is_valid, to: Done)\n"
" |> config.set_final_states([Done, Failed])\n"
" |> config.set_on_enter(Running, start_handler)\n"
" |> config.set_event_policy(config.Ignore)\n"
" |> config.set_history_limit(100)\n"
" ```\n"
).
-type event_policy() :: reject | ignore.
-type transition_rule(FIV, FIW, FIX) :: {transition_rule,
FIV,
FIX,
FIV,
gleam@option:option(fun((FIW, FIX) -> boolean()))}.
-opaque config(FIY, FIZ, FJA) :: {config,
list(transition_rule(FIY, FIZ, FJA)),
list(FIY),
list({FIY, fun((FIY, FIZ) -> {ok, FIZ} | {error, binary()})}),
list({FIY, fun((FIY, FIZ) -> {ok, FIZ} | {error, binary()})}),
list({FIY, fun((FIY, FJA, FIY, FIZ) -> {ok, FIZ} | {error, binary()})}),
list(fun((FIY, FIZ) -> {ok, FIZ} | {error, binary()})),
list(fun((FIY, FIZ) -> {ok, FIZ} | {error, binary()})),
list(fun((FIY, FJA, FIY, FIZ) -> {ok, FIZ} | {error, binary()})),
list(fun((FIZ) -> {ok, nil} | {error, binary()})),
event_policy(),
gleam@option:option(integer()),
boolean(),
list({FIY, integer(), FJA}),
fun(() -> integer())}.
-file("src/scamper/config.gleam", 85).
?DOC(
" Create a new empty configuration.\n"
" The `timestamp_fn` is called to get the current time in milliseconds.\n"
).
-spec new(fun(() -> integer())) -> config(any(), any(), any()).
new(Timestamp_fn) ->
{config,
[],
[],
[],
[],
[],
[],
[],
[],
[],
reject,
none,
false,
[],
Timestamp_fn}.
-file("src/scamper/config.gleam", 105).
?DOC(" Add a simple (unguarded) transition rule.\n").
-spec add_transition(config(FJQ, FJR, FJS), FJQ, FJS, FJQ) -> config(FJQ, FJR, FJS).
add_transition(Config, From, On, To) ->
Rule = {transition_rule, From, On, To, none},
{config,
lists:append(erlang:element(2, Config), [Rule]),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 116).
?DOC(" Add a guarded transition rule.\n").
-spec add_guarded_transition(
config(FJZ, FKA, FKB),
FJZ,
FKB,
fun((FKA, FKB) -> boolean()),
FJZ
) -> config(FJZ, FKA, FKB).
add_guarded_transition(Config, From, On, Guard, To) ->
Rule = {transition_rule, From, On, To, {some, Guard}},
{config,
lists:append(erlang:element(2, Config), [Rule]),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 128).
?DOC(" Set the list of final (terminal) states.\n").
-spec set_final_states(config(FKI, FKJ, FKK), list(FKI)) -> config(FKI, FKJ, FKK).
set_final_states(Config, States) ->
{config,
erlang:element(2, Config),
States,
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 136).
?DOC(" Set a state-specific on_enter callback.\n").
-spec set_on_enter(
config(FKS, FKT, FKU),
FKS,
fun((FKS, FKT) -> {ok, FKT} | {error, binary()})
) -> config(FKS, FKT, FKU).
set_on_enter(Config, State, Callback) ->
On_enter = begin
_pipe = erlang:element(4, Config),
_pipe@1 = gleam@list:filter(
_pipe,
fun(Entry) -> erlang:element(1, Entry) /= State end
),
lists:append(_pipe@1, [{State, Callback}])
end,
{config,
erlang:element(2, Config),
erlang:element(3, Config),
On_enter,
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 149).
?DOC(" Set a state-specific on_exit callback.\n").
-spec set_on_exit(
config(FLD, FLE, FLF),
FLD,
fun((FLD, FLE) -> {ok, FLE} | {error, binary()})
) -> config(FLD, FLE, FLF).
set_on_exit(Config, State, Callback) ->
On_exit = begin
_pipe = erlang:element(5, Config),
_pipe@1 = gleam@list:filter(
_pipe,
fun(Entry) -> erlang:element(1, Entry) /= State end
),
lists:append(_pipe@1, [{State, Callback}])
end,
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
On_exit,
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 162).
?DOC(" Set a state-specific on_transition callback (keyed by from-state).\n").
-spec set_on_transition(
config(FLO, FLP, FLQ),
FLO,
fun((FLO, FLQ, FLO, FLP) -> {ok, FLP} | {error, binary()})
) -> config(FLO, FLP, FLQ).
set_on_transition(Config, State, Callback) ->
On_transition_state = begin
_pipe = erlang:element(6, Config),
_pipe@1 = gleam@list:filter(
_pipe,
fun(Entry) -> erlang:element(1, Entry) /= State end
),
lists:append(_pipe@1, [{State, Callback}])
end,
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
On_transition_state,
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 175).
?DOC(" Add a global on_enter callback (runs for all transitions).\n").
-spec add_global_on_enter(
config(FMA, FMB, FMC),
fun((FMA, FMB) -> {ok, FMB} | {error, binary()})
) -> config(FMA, FMB, FMC).
add_global_on_enter(Config, Callback) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
lists:append(erlang:element(7, Config), [Callback]),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 186).
?DOC(" Add a global on_exit callback (runs for all transitions).\n").
-spec add_global_on_exit(
config(FML, FMM, FMN),
fun((FML, FMM) -> {ok, FMM} | {error, binary()})
) -> config(FML, FMM, FMN).
add_global_on_exit(Config, Callback) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
lists:append(erlang:element(8, Config), [Callback]),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 197).
?DOC(" Add a global on_transition callback (runs for all transitions).\n").
-spec add_global_on_transition(
config(FMW, FMX, FMY),
fun((FMW, FMY, FMW, FMX) -> {ok, FMX} | {error, binary()})
) -> config(FMW, FMX, FMY).
add_global_on_transition(Config, Callback) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
lists:append(erlang:element(9, Config), [Callback]),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 208).
?DOC(" Add a context invariant that is checked after every successful transition.\n").
-spec add_invariant(
config(FNI, FNJ, FNK),
fun((FNJ) -> {ok, nil} | {error, binary()})
) -> config(FNI, FNJ, FNK).
add_invariant(Config, Invariant) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
lists:append(erlang:element(10, Config), [Invariant]),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 216).
?DOC(" Set the event filtering policy.\n").
-spec set_event_policy(config(FNT, FNU, FNV), event_policy()) -> config(FNT, FNU, FNV).
set_event_policy(Config, Policy) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
Policy,
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 224).
?DOC(" Set the maximum number of history records to keep.\n").
-spec set_history_limit(config(FOC, FOD, FOE), integer()) -> config(FOC, FOD, FOE).
set_history_limit(Config, Limit) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
{some, Limit},
erlang:element(13, Config),
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 232).
?DOC(" Set whether to include context snapshots in history records.\n").
-spec set_history_snapshots(config(FOL, FOM, FON), boolean()) -> config(FOL, FOM, FON).
set_history_snapshots(Config, Enabled) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
Enabled,
erlang:element(14, Config),
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 242).
?DOC(
" Declare a timeout for a state.\n"
" After `duration_ms` milliseconds in `state`, the `timeout_event` should be sent.\n"
" The library only declares this — actual timer management is external.\n"
).
-spec set_timeout(config(FOU, FOV, FOW), FOU, integer(), FOW) -> config(FOU, FOV, FOW).
set_timeout(Config, State, Duration_ms, Timeout_event) ->
Timeouts = begin
_pipe = erlang:element(14, Config),
_pipe@1 = gleam@list:filter(
_pipe,
fun(Entry) -> erlang:element(1, Entry) /= State end
),
lists:append(_pipe@1, [{State, Duration_ms, Timeout_event}])
end,
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
Timeouts,
erlang:element(15, Config)}.
-file("src/scamper/config.gleam", 258).
?DOC(" Get the transition rules list.\n").
-spec get_transitions(config(FPD, FPE, FPF)) -> list(transition_rule(FPD, FPE, FPF)).
get_transitions(Config) ->
erlang:element(2, Config).
-file("src/scamper/config.gleam", 265).
?DOC(" Get the final states list.\n").
-spec get_final_states(config(FPN, any(), any())) -> list(FPN).
get_final_states(Config) ->
erlang:element(3, Config).
-file("src/scamper/config.gleam", 270).
?DOC(" Get state-specific on_enter callbacks.\n").
-spec get_on_enter(config(FPU, FPV, any())) -> list({FPU,
fun((FPU, FPV) -> {ok, FPV} | {error, binary()})}).
get_on_enter(Config) ->
erlang:element(4, Config).
-file("src/scamper/config.gleam", 277).
?DOC(" Get state-specific on_exit callbacks.\n").
-spec get_on_exit(config(FQD, FQE, any())) -> list({FQD,
fun((FQD, FQE) -> {ok, FQE} | {error, binary()})}).
get_on_exit(Config) ->
erlang:element(5, Config).
-file("src/scamper/config.gleam", 284).
?DOC(" Get state-specific on_transition callbacks.\n").
-spec get_on_transition_state(config(FQM, FQN, FQO)) -> list({FQM,
fun((FQM, FQO, FQM, FQN) -> {ok, FQN} | {error, binary()})}).
get_on_transition_state(Config) ->
erlang:element(6, Config).
-file("src/scamper/config.gleam", 291).
?DOC(" Get global on_enter callbacks.\n").
-spec get_global_on_enter(config(FQW, FQX, any())) -> list(fun((FQW, FQX) -> {ok,
FQX} |
{error, binary()})).
get_global_on_enter(Config) ->
erlang:element(7, Config).
-file("src/scamper/config.gleam", 298).
?DOC(" Get global on_exit callbacks.\n").
-spec get_global_on_exit(config(FRF, FRG, any())) -> list(fun((FRF, FRG) -> {ok,
FRG} |
{error, binary()})).
get_global_on_exit(Config) ->
erlang:element(8, Config).
-file("src/scamper/config.gleam", 305).
?DOC(" Get global on_transition callbacks.\n").
-spec get_global_on_transition(config(FRO, FRP, FRQ)) -> list(fun((FRO, FRQ, FRO, FRP) -> {ok,
FRP} |
{error, binary()})).
get_global_on_transition(Config) ->
erlang:element(9, Config).
-file("src/scamper/config.gleam", 312).
?DOC(" Get context invariants.\n").
-spec get_invariants(config(any(), FRZ, any())) -> list(fun((FRZ) -> {ok, nil} |
{error, binary()})).
get_invariants(Config) ->
erlang:element(10, Config).
-file("src/scamper/config.gleam", 319).
?DOC(" Get the event policy.\n").
-spec get_event_policy(config(any(), any(), any())) -> event_policy().
get_event_policy(Config) ->
erlang:element(11, Config).
-file("src/scamper/config.gleam", 324).
?DOC(" Get the history limit.\n").
-spec get_history_limit(config(any(), any(), any())) -> gleam@option:option(integer()).
get_history_limit(Config) ->
erlang:element(12, Config).
-file("src/scamper/config.gleam", 329).
?DOC(" Get whether history snapshots are enabled.\n").
-spec get_history_snapshots(config(any(), any(), any())) -> boolean().
get_history_snapshots(Config) ->
erlang:element(13, Config).
-file("src/scamper/config.gleam", 334).
?DOC(" Get timeout declarations.\n").
-spec get_timeouts(config(FTA, any(), FTC)) -> list({FTA, integer(), FTC}).
get_timeouts(Config) ->
erlang:element(14, Config).
-file("src/scamper/config.gleam", 341).
?DOC(" Get the current timestamp by calling the configured timestamp function.\n").
-spec get_timestamp(config(any(), any(), any())) -> integer().
get_timestamp(Config) ->
(erlang:element(15, Config))().
-file("src/scamper/config.gleam", 346).
?DOC(" Get the timestamp function itself.\n").
-spec get_timestamp_fn(config(any(), any(), any())) -> fun(() -> integer()).
get_timestamp_fn(Config) ->
erlang:element(15, Config).