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