Skip to content
Snippets Groups Projects
Select Git revision
  • f15a1d52e94dea8219cc6be3e58a3e372131e637
  • master default protected
  • refactor/PRXS-3053-Files
  • feature/PRXS-3143-3235-ReferenceOptions
  • feature/PRXS-3421-ImplementNewRefAPI
  • feature/PRXS-3143-LimitReferenceFields
  • feature/PRXS-3234-FeaturePruneIdents
  • feature/3149-LocaleCodeAsID-Feature
  • feature/PRXS-3383-CollectionsRankSortAPI
  • PRXS-3421-RecursiveReferences
  • feature/PRXS-3383-CollectionsSort
  • feature/3109-SerializeFeature
  • release/0.33
  • feature/3109-RecoverySchema
  • feature/3109-feature
  • fix/PRXS-3369-ValidateFields
  • refactor/PRXS-3306-MovePkgGroup1
  • refactor/6-pkg-refactor-expr
  • fix/PRXS-3360-TemplateBuilderPatch
  • feature/3293-MongoV2
  • feature/3272-GoVersionUp
  • v0.33.1
  • v0.32.0
  • v0.31.1
  • v0.31.0
  • v0.30.0
  • v0.29.0
  • v0.28.0
  • v0.27.0-alpha.1+16
  • v0.27.0-alpha.1+15
  • v0.27.0-alpha.1+14
  • v0.27.0-alpha.1+13
  • v0.27.0-alpha.1+12
  • v0.27.0-alpha.1+11
  • v0.27.0-alpha.1+10
  • v0.27.0-alpha.1+9
  • v0.27.0-alpha.1+8
  • v0.27.0-alpha.1+7
  • v0.27.0-alpha.1+6
  • v0.27.0-alpha.1+5
  • v0.27.0-alpha.1+4
41 results

template_executor.go

Blame
  • Semyon Krestyaninov's avatar
    Semyon Krestyaninov authored
    61569793
    History
    template_executor.go 1.74 KiB
    package executor
    
    import (
    	"bytes"
    	"context"
    	"sync"
    	"text/template"
    
    	"git.perx.ru/perxis/perxis-go/pkg/errors"
    )
    
    type TemplateExecutor struct {
    	data    map[string]any
    	funcMap template.FuncMap
    }
    
    func NewTemplateExecutor(data map[string]any) *TemplateExecutor {
    	te := &TemplateExecutor{
    		data: data,
    	}
    	te.init()
    	return te
    }
    
    func (exec *TemplateExecutor) init() {
    	if exec.data == nil {
    		exec.data = make(map[string]any)
    	}
    	delete(exec.data, "Error")
    
    	exec.funcMap = template.FuncMap{
    		"error": exec.errorFunc,
    	}
    }
    
    func (exec *TemplateExecutor) Execute(_ context.Context, input string) (string, error) {
    	templ, err := template.New("template_executor").Funcs(exec.funcMap).Parse(input)
    	if err != nil {
    		return "", err
    	}
    
    	buf := getBuffer()
    	defer releaseBuffer(buf)
    
    	err = templ.Execute(buf, exec.data)
    	if err != nil {
    		return "", err
    	}
    
    	output := buf.String()
    	if output == "<no value>" {
    		return "", nil
    	}
    
    	return output, nil
    }
    
    // IsCanceled возвращает true, если в процессе выполнения шаблона была вызвана
    // шаблонная функция error.
    func (exec *TemplateExecutor) IsCanceled() bool {
    	_, ok := exec.data["Error"]
    	return ok
    }
    
    func (exec *TemplateExecutor) errorFunc(text string) (string, error) {
    	exec.data["Error"] = text
    	return "", errors.New(text)
    }
    
    //nolint:gochecknoglobals // Доступ к пулу необходим на глобальном уровне.
    var bufferPool = &sync.Pool{
    	New: func() any {
    		return new(bytes.Buffer)
    	},
    }
    
    func getBuffer() *bytes.Buffer {
    	buf, _ := bufferPool.Get().(*bytes.Buffer)
    	return buf
    }
    
    func releaseBuffer(buf *bytes.Buffer) {
    	const maxBufCap = 1024
    	if buf.Cap() > maxBufCap {
    		return
    	}
    	buf.Reset()
    	bufferPool.Put(buf)
    }