package host
import (
"context"
"encoding/json"
extism "github.com/extism/go-sdk"
)
type CacheSetStringRequest struct {
Key string `json:"key"`
Value string `json:"value"`
TtlSeconds int64 `json:"ttlSeconds"`
}
type CacheSetStringResponse struct {
Error string `json:"error,omitempty"`
}
type CacheGetStringRequest struct {
Key string `json:"key"`
}
type CacheGetStringResponse struct {
Value string `json:"value,omitempty"`
Exists bool `json:"exists,omitempty"`
Error string `json:"error,omitempty"`
}
type CacheSetIntRequest struct {
Key string `json:"key"`
Value int64 `json:"value"`
TtlSeconds int64 `json:"ttlSeconds"`
}
type CacheSetIntResponse struct {
Error string `json:"error,omitempty"`
}
type CacheGetIntRequest struct {
Key string `json:"key"`
}
type CacheGetIntResponse struct {
Value int64 `json:"value,omitempty"`
Exists bool `json:"exists,omitempty"`
Error string `json:"error,omitempty"`
}
type CacheSetFloatRequest struct {
Key string `json:"key"`
Value float64 `json:"value"`
TtlSeconds int64 `json:"ttlSeconds"`
}
type CacheSetFloatResponse struct {
Error string `json:"error,omitempty"`
}
type CacheGetFloatRequest struct {
Key string `json:"key"`
}
type CacheGetFloatResponse struct {
Value float64 `json:"value,omitempty"`
Exists bool `json:"exists,omitempty"`
Error string `json:"error,omitempty"`
}
type CacheSetBytesRequest struct {
Key string `json:"key"`
Value []byte `json:"value"`
TtlSeconds int64 `json:"ttlSeconds"`
}
type CacheSetBytesResponse struct {
Error string `json:"error,omitempty"`
}
type CacheGetBytesRequest struct {
Key string `json:"key"`
}
type CacheGetBytesResponse struct {
Value []byte `json:"value,omitempty"`
Exists bool `json:"exists,omitempty"`
Error string `json:"error,omitempty"`
}
type CacheHasRequest struct {
Key string `json:"key"`
}
type CacheHasResponse struct {
Exists bool `json:"exists,omitempty"`
Error string `json:"error,omitempty"`
}
type CacheRemoveRequest struct {
Key string `json:"key"`
}
type CacheRemoveResponse struct {
Error string `json:"error,omitempty"`
}
func RegisterCacheHostFunctions(service CacheService) []extism.HostFunction {
return []extism.HostFunction{
newCacheSetStringHostFunction(service),
newCacheGetStringHostFunction(service),
newCacheSetIntHostFunction(service),
newCacheGetIntHostFunction(service),
newCacheSetFloatHostFunction(service),
newCacheGetFloatHostFunction(service),
newCacheSetBytesHostFunction(service),
newCacheGetBytesHostFunction(service),
newCacheHasHostFunction(service),
newCacheRemoveHostFunction(service),
}
}
func newCacheSetStringHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_setstring",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheSetStringRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
if svcErr := service.SetString(ctx, req.Key, req.Value, req.TtlSeconds); svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheSetStringResponse{}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func newCacheGetStringHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_getstring",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheGetStringRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
value, exists, svcErr := service.GetString(ctx, req.Key)
if svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheGetStringResponse{
Value: value,
Exists: exists,
}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func newCacheSetIntHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_setint",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheSetIntRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
if svcErr := service.SetInt(ctx, req.Key, req.Value, req.TtlSeconds); svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheSetIntResponse{}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func newCacheGetIntHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_getint",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheGetIntRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
value, exists, svcErr := service.GetInt(ctx, req.Key)
if svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheGetIntResponse{
Value: value,
Exists: exists,
}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func newCacheSetFloatHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_setfloat",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheSetFloatRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
if svcErr := service.SetFloat(ctx, req.Key, req.Value, req.TtlSeconds); svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheSetFloatResponse{}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func newCacheGetFloatHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_getfloat",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheGetFloatRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
value, exists, svcErr := service.GetFloat(ctx, req.Key)
if svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheGetFloatResponse{
Value: value,
Exists: exists,
}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func newCacheSetBytesHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_setbytes",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheSetBytesRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
if svcErr := service.SetBytes(ctx, req.Key, req.Value, req.TtlSeconds); svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheSetBytesResponse{}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func newCacheGetBytesHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_getbytes",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheGetBytesRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
value, exists, svcErr := service.GetBytes(ctx, req.Key)
if svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheGetBytesResponse{
Value: value,
Exists: exists,
}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func newCacheHasHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_has",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheHasRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
exists, svcErr := service.Has(ctx, req.Key)
if svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheHasResponse{
Exists: exists,
}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func newCacheRemoveHostFunction(service CacheService) extism.HostFunction {
return extism.NewHostFunctionWithStack(
"cache_remove",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
reqBytes, err := p.ReadBytes(stack[0])
if err != nil {
cacheWriteError(p, stack, err)
return
}
var req CacheRemoveRequest
if err := json.Unmarshal(reqBytes, &req); err != nil {
cacheWriteError(p, stack, err)
return
}
if svcErr := service.Remove(ctx, req.Key); svcErr != nil {
cacheWriteError(p, stack, svcErr)
return
}
resp := CacheRemoveResponse{}
cacheWriteResponse(p, stack, resp)
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{extism.ValueTypePTR},
)
}
func cacheWriteResponse(p *extism.CurrentPlugin, stack []uint64, resp any) {
respBytes, err := json.Marshal(resp)
if err != nil {
cacheWriteError(p, stack, err)
return
}
respPtr, err := p.WriteBytes(respBytes)
if err != nil {
stack[0] = 0
return
}
stack[0] = respPtr
}
func cacheWriteError(p *extism.CurrentPlugin, stack []uint64, err error) {
errResp := struct {
Error string `json:"error"`
}{Error: err.Error()}
respBytes, _ := json.Marshal(errResp)
respPtr, _ := p.WriteBytes(respBytes)
stack[0] = respPtr
}