resource.go (5251B)
1 package resource 2 3 import ( 4 "context" 5 "fmt" 6 ) 7 8 // Result contains the results of an external code operation. 9 type Result struct { 10 // content value for symbol after execution. 11 Content string 12 // application defined status code which can complement error returns 13 Status int 14 // request caller to set error flags at given indices. 15 FlagSet []uint32 16 // request caller to reset error flags at given indices. 17 FlagReset []uint32 18 } 19 20 // EntryFunc is a function signature for a function that resolves the symbol of a LOAD instruction. 21 // 22 // The EntryFunc receives the current input buffer from the client, aswell as the symbol of the current state node being executed. 23 // 24 // The implementer MUST NOT modify state flags or cache inside the function. The resource.Result object MUST be used instead. 25 type EntryFunc func(ctx context.Context, nodeSym string, input []byte) (Result, error) 26 27 // CodeFunc is the function signature for retrieving bytecode for a given symbol. 28 type CodeFunc func(ctx context.Context, nodeSym string) ([]byte, error) 29 30 // MenuFunc is the function signature for retrieving menu symbol resolution. 31 type MenuFunc func(ctx context.Context, menuSym string) (string, error) 32 33 // TemplateFunc is the function signature for retrieving a render template for a given symbol. 34 type TemplateFunc func(ctx context.Context, nodeSym string) (string, error) 35 36 // FuncForFunc is a function that returns an EntryFunc associated with a LOAD instruction symbol. 37 type FuncForFunc func(ctx context.Context, loadSym string) (EntryFunc, error) 38 39 // Resource implementation are responsible for retrieving values and templates for symbols, and can render templates from value dictionaries. 40 // 41 // All methods must fail if the symbol cannot be resolved. 42 type Resource interface { 43 // GetTemplate retrieves a render template associated with the given symbol. 44 GetTemplate(ctx context.Context, nodeSym string) (string, error) 45 // GetCode retrieves the bytecode associated with the given symbol. 46 GetCode(ctx context.Context, nodeSym string) ([]byte, error) 47 // GetMenu retrieves the menu label associated with the given symbol. 48 GetMenu(ctx context.Context, menuSym string) (string, error) 49 // FuncFor retrieves the external function (EntryFunc) associated with the given symbol. 50 FuncFor(ctx context.Context, loadSym string) (EntryFunc, error) 51 // Safely shuts down retrieval backend. 52 Close(ctx context.Context) error 53 } 54 55 // MenuResource contains the base definition for building Resource implementations. 56 type MenuResource struct { 57 sinkValues []string 58 codeFunc CodeFunc 59 templateFunc TemplateFunc 60 menuFunc MenuFunc 61 funcFunc FuncForFunc 62 fns map[string]EntryFunc 63 } 64 65 var ( 66 noBinFunc = func(ctx context.Context, s string) ([]byte, error) { 67 logg.WarnCtxf(ctx, "no resource getter set!", "s", s) 68 return []byte{}, nil 69 } 70 noStrFunc = func(ctx context.Context, s string) (string, error) { 71 logg.WarnCtxf(ctx, "no resource getter set!", "s", s) 72 return "", nil 73 } 74 ) 75 76 // NewMenuResource creates a new MenuResource instance. 77 func NewMenuResource() *MenuResource { 78 rs := &MenuResource{} 79 rs.funcFunc = rs.FallbackFunc 80 rs.codeFunc = noBinFunc 81 rs.templateFunc = noStrFunc 82 rs.menuFunc = noStrFunc 83 return rs 84 } 85 86 // WithCodeGetter sets the code symbol resolver method. 87 func (m *MenuResource) WithCodeGetter(codeGetter CodeFunc) *MenuResource { 88 m.codeFunc = codeGetter 89 return m 90 } 91 92 // WithEntryGetter sets the content symbol resolver getter method. 93 func (m *MenuResource) WithEntryFuncGetter(entryFuncGetter FuncForFunc) *MenuResource { 94 m.funcFunc = entryFuncGetter 95 return m 96 } 97 98 // WithTemplateGetter sets the template symbol resolver method. 99 func (m *MenuResource) WithTemplateGetter(templateGetter TemplateFunc) *MenuResource { 100 m.templateFunc = templateGetter 101 return m 102 } 103 104 // WithMenuGetter sets the menu symbol resolver method. 105 func (m *MenuResource) WithMenuGetter(menuGetter MenuFunc) *MenuResource { 106 m.menuFunc = menuGetter 107 return m 108 } 109 110 // FuncFor implements Resource interface. 111 func (m *MenuResource) FuncFor(ctx context.Context, sym string) (EntryFunc, error) { 112 return m.funcFunc(ctx, sym) 113 } 114 115 // GetCode implements Resource interface. 116 func (m *MenuResource) GetCode(ctx context.Context, sym string) ([]byte, error) { 117 return m.codeFunc(ctx, sym) 118 } 119 120 // GetTemplate implements Resource interface. 121 func (m *MenuResource) GetTemplate(ctx context.Context, sym string) (string, error) { 122 return m.templateFunc(ctx, sym) 123 } 124 125 // GetMenu implements Resource interface. 126 func (m *MenuResource) GetMenu(ctx context.Context, sym string) (string, error) { 127 return m.menuFunc(ctx, sym) 128 } 129 130 // AddLocalFunc associates a handler function with a external function symbol to be returned by FallbackFunc. 131 func (m *MenuResource) AddLocalFunc(sym string, fn EntryFunc) { 132 if m.fns == nil { 133 m.fns = make(map[string]EntryFunc) 134 } 135 m.fns[sym] = fn 136 } 137 138 // FallbackFunc returns the default handler function for a given external function symbol. 139 func (m *MenuResource) FallbackFunc(ctx context.Context, sym string) (EntryFunc, error) { 140 fn, ok := m.fns[sym] 141 if !ok { 142 return nil, fmt.Errorf("unknown function: %s", sym) 143 } 144 return fn, nil 145 } 146 147 // Close implements the Resource interface. 148 func (m *MenuResource) Close(ctx context.Context) error { 149 return nil 150 }