parser
API
parser
packageAPI reference for the parser
package.
Imports
(5)
S
struct
Config
Config holds the parsed FSM definition from a tag.
pkg/fsm/parser/parser.go:12-17
type Config struct
Fields
| Name | Type | Description |
|---|---|---|
| InitialState | string | |
| Transitions | map[string][]string | |
| Wildcards | []string | |
| Timeouts | map[string]TimeoutRule |
S
struct
TimeoutRule
TimeoutRule defines an automatic transition after a duration.
pkg/fsm/parser/parser.go:20-24
type TimeoutRule struct
Fields
| Name | Type | Description |
|---|---|---|
| FromState | string | |
| ToState | string | |
| Duration | time.Duration |
F
function
Parse
Parse parses an FSM tag string into a Config.
Parameters
tag
string
Returns
error
pkg/fsm/parser/parser.go:29-86
func Parse(tag string) (*Config, error)
{
cfg := &Config{
Transitions: make(map[string][]string),
Timeouts: make(map[string]TimeoutRule),
}
parsed := tagParser.Parse(tag)
if initial, ok := parsed["initial"]; ok && len(initial) > 0 {
cfg.InitialState = initial[0]
}
for key := range parsed {
if key == "initial" {
continue
}
part := key
var timeoutDuration time.Duration
if startBracket := strings.Index(part, "["); startBracket != -1 {
endBracket := strings.Index(part, "]")
if endBracket > startBracket {
durStr := part[startBracket+1 : endBracket]
var err error
timeoutDuration, err = time.ParseDuration(durStr)
if err != nil {
return nil, fmt.Errorf("invalid timeout duration: %s", durStr)
}
part = strings.TrimSpace(part[:startBracket])
}
}
before, after, ok := strings.Cut(part, "->")
if !ok {
continue
}
src := strings.TrimSpace(before)
dst := strings.TrimSpace(after)
if src == "*" {
cfg.Wildcards = append(cfg.Wildcards, dst)
} else {
cfg.Transitions[src] = append(cfg.Transitions[src], dst)
}
if timeoutDuration > 0 {
cfg.Timeouts[src] = TimeoutRule{
FromState: src,
ToState: dst,
Duration: timeoutDuration,
}
}
}
return cfg, nil
}
F
function
TestParse_BasicTransition
Parameters
t
pkg/fsm/parser/parser_test.go:8-25
func TestParse_BasicTransition(t *testing.T)
{
cfg, err := Parse("initial:draft; draft->paid; paid->shipped")
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
if cfg.InitialState != "draft" {
t.Errorf("initial = %q, want %q", cfg.InitialState, "draft")
}
if len(cfg.Transitions) != 2 {
t.Fatalf("expected 2 transitions, got %d", len(cfg.Transitions))
}
if !contains(cfg.Transitions["draft"], "paid") {
t.Error("expected draft->paid")
}
if !contains(cfg.Transitions["paid"], "shipped") {
t.Error("expected paid->shipped")
}
}
F
function
TestParse_Wildcard
Parameters
t
pkg/fsm/parser/parser_test.go:27-35
func TestParse_Wildcard(t *testing.T)
{
cfg, err := Parse("initial:active; *->cancelled")
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
if len(cfg.Wildcards) != 1 || cfg.Wildcards[0] != "cancelled" {
t.Errorf("wildcards = %v, want [cancelled]", cfg.Wildcards)
}
}
F
function
TestParse_Timeout
Parameters
t
pkg/fsm/parser/parser_test.go:37-52
func TestParse_Timeout(t *testing.T)
{
cfg, err := Parse("initial:pending; pending->expired [500ms]")
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
rule, ok := cfg.Timeouts["pending"]
if !ok {
t.Fatal("expected timeout for 'pending'")
}
if rule.ToState != "expired" {
t.Errorf("toState = %q, want %q", rule.ToState, "expired")
}
if rule.Duration != 500*time.Millisecond {
t.Errorf("duration = %v, want %v", rule.Duration, 500*time.Millisecond)
}
}
F
function
TestParse_TimeoutCustomDuration
Parameters
t
pkg/fsm/parser/parser_test.go:54-66
func TestParse_TimeoutCustomDuration(t *testing.T)
{
cfg, err := Parse("a->b [2s]")
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
rule, ok := cfg.Timeouts["a"]
if !ok {
t.Fatal("expected timeout for 'a'")
}
if rule.Duration != 2*time.Second {
t.Errorf("duration = %v, want %v", rule.Duration, 2*time.Second)
}
}
F
function
TestParse_MultipleTransitionsFromSameState
Parameters
t
pkg/fsm/parser/parser_test.go:68-76
func TestParse_MultipleTransitionsFromSameState(t *testing.T)
{
cfg, err := Parse("a->b; a->c; b->d")
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
if len(cfg.Transitions["a"]) != 2 {
t.Fatalf("expected 2 transitions from 'a', got %d", len(cfg.Transitions["a"]))
}
}
F
function
TestParse_NoInitial
Parameters
t
pkg/fsm/parser/parser_test.go:78-86
func TestParse_NoInitial(t *testing.T)
{
cfg, err := Parse("a->b")
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
if cfg.InitialState != "" {
t.Errorf("expected empty initial, got %q", cfg.InitialState)
}
}
F
function
TestParse_InvalidDuration
Parameters
t
pkg/fsm/parser/parser_test.go:88-93
func TestParse_InvalidDuration(t *testing.T)
{
_, err := Parse("a->b [notaduration]")
if err == nil {
t.Fatal("expected error for invalid duration")
}
}
F
function
TestParse_TrimsWhitespace
Parameters
t
pkg/fsm/parser/parser_test.go:95-106
func TestParse_TrimsWhitespace(t *testing.T)
{
cfg, err := Parse(" initial: draft ; draft -> paid ")
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
if cfg.InitialState != "draft" {
t.Errorf("initial = %q, want %q", cfg.InitialState, "draft")
}
if !contains(cfg.Transitions["draft"], "paid") {
t.Error("expected draft->paid")
}
}
F
function
TestParse_EmptyTag
Parameters
t
pkg/fsm/parser/parser_test.go:108-116
func TestParse_EmptyTag(t *testing.T)
{
cfg, err := Parse("")
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
if cfg.InitialState != "" || len(cfg.Transitions) != 0 {
t.Error("expected empty config for empty tag")
}
}
F
function
TestParse_MultipleWildcards
Parameters
t
pkg/fsm/parser/parser_test.go:118-126
func TestParse_MultipleWildcards(t *testing.T)
{
cfg, err := Parse("*->cancelled; *->archived")
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
if len(cfg.Wildcards) != 2 {
t.Fatalf("expected 2 wildcards, got %v", cfg.Wildcards)
}
}
F
function
contains
Parameters
slice
[]string
s
string
Returns
bool
pkg/fsm/parser/parser_test.go:128-135
func contains(slice []string, s string) bool
{
for _, v := range slice {
if v == s {
return true
}
}
return false
}
S
struct
Policy
Policy represents the security rules extracted from a struct tag.
pkg/guard/parser/parser.go:8-12
type Policy struct
Fields
| Name | Type | Description |
|---|---|---|
| Roles | []string | |
| Permissions | map[string][]string | |
| UseValueAsRole | bool |
F
function
Parse
Parse extracts policy information from a ‘guard’ struct tag.
Parameters
tag
string
Returns
pkg/guard/parser/parser.go:17-38
func Parse(tag string) *Policy
{
p := &Policy{
Permissions: make(map[string][]string),
}
parsed := tagParser.Parse(tag)
for key, values := range parsed {
if key == "role" {
if len(values) == 1 && values[0] == "*" {
p.UseValueAsRole = true
} else {
p.Roles = append(p.Roles, values...)
}
continue
}
p.Permissions[key] = values
}
return p
}