-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).