github.com/kubeshop/testkube@v1.17.23/cmd/tcl/testworkflow-init/data/emit.go (about)

     1  // Copyright 2024 Testkube.
     2  //
     3  // Licensed as a Testkube Pro file under the Testkube Community
     4  // License (the "License"); you may not use this file except in compliance with
     5  // the License. You may obtain a copy of the License at
     6  //
     7  //	https://github.com/kubeshop/testkube/blob/main/licenses/TCL.txt
     8  
     9  package data
    10  
    11  import (
    12  	"encoding/json"
    13  	"fmt"
    14  	"regexp"
    15  	"strings"
    16  )
    17  
    18  const (
    19  	InstructionPrefix         = "\u0001\u0005"
    20  	HintPrefix                = "\u0006"
    21  	InstructionSeparator      = "\u0003"
    22  	InstructionValueSeparator = "\u0004"
    23  )
    24  
    25  var instructionRe = regexp.MustCompile(fmt.Sprintf(`^%s(%s)?([^%s]+)%s([a-zA-Z0-9-_.]+)(?:%s([^\n]+))?%s$`,
    26  	InstructionPrefix, HintPrefix, InstructionSeparator, InstructionSeparator, InstructionValueSeparator, InstructionSeparator))
    27  
    28  type Instruction struct {
    29  	Ref   string
    30  	Name  string
    31  	Value interface{}
    32  }
    33  
    34  func SprintOutput(ref string, name string, value interface{}) string {
    35  	j, err := json.Marshal(value)
    36  	if err != nil {
    37  		panic(fmt.Sprintf("error while marshalling reference: %v", err))
    38  	}
    39  	var sb strings.Builder
    40  	sb.WriteString("\n")
    41  	sb.WriteString(InstructionPrefix)
    42  	sb.WriteString(ref)
    43  	sb.WriteString(InstructionSeparator)
    44  	sb.WriteString(name)
    45  	sb.WriteString(InstructionValueSeparator)
    46  	sb.Write(j)
    47  	sb.WriteString(InstructionSeparator)
    48  	sb.WriteString("\n")
    49  	return sb.String()
    50  }
    51  
    52  func SprintHint(ref string, name string) string {
    53  	var sb strings.Builder
    54  	sb.WriteString("\n")
    55  	sb.WriteString(InstructionPrefix)
    56  	sb.WriteString(HintPrefix)
    57  	sb.WriteString(ref)
    58  	sb.WriteString(InstructionSeparator)
    59  	sb.WriteString(name)
    60  	sb.WriteString(InstructionSeparator)
    61  	sb.WriteString("\n")
    62  	return sb.String()
    63  }
    64  
    65  func SprintHintDetails(ref string, name string, value interface{}) string {
    66  	j, err := json.Marshal(value)
    67  	if err != nil {
    68  		panic(fmt.Sprintf("error while marshalling reference: %v", err))
    69  	}
    70  	var sb strings.Builder
    71  	sb.WriteString("\n")
    72  	sb.WriteString(InstructionPrefix)
    73  	sb.WriteString(HintPrefix)
    74  	sb.WriteString(ref)
    75  	sb.WriteString(InstructionSeparator)
    76  	sb.WriteString(name)
    77  	sb.WriteString(InstructionValueSeparator)
    78  	sb.Write(j)
    79  	sb.WriteString(InstructionSeparator)
    80  	sb.WriteString("\n")
    81  	return sb.String()
    82  }
    83  
    84  func PrintOutput(ref string, name string, value interface{}) {
    85  	fmt.Print(SprintOutput(ref, name, value))
    86  }
    87  
    88  func PrintHint(ref string, name string) {
    89  	fmt.Print(SprintHint(ref, name))
    90  }
    91  
    92  func PrintHintDetails(ref string, name string, value interface{}) {
    93  	fmt.Print(SprintHintDetails(ref, name, value))
    94  }
    95  
    96  func DetectInstruction(line []byte) (*Instruction, bool, error) {
    97  	// Fast check to avoid regexes
    98  	if len(line) < 4 || string(line[0:len(InstructionPrefix)]) != InstructionPrefix || string(line[:len(InstructionPrefix)]) != InstructionPrefix {
    99  		return nil, false, nil
   100  	}
   101  	// Parse the line
   102  	v := instructionRe.FindSubmatch(line)
   103  	if v == nil {
   104  		return nil, false, nil
   105  	}
   106  	isHint := string(v[1]) == HintPrefix
   107  	instruction := &Instruction{
   108  		Ref:  string(v[2]),
   109  		Name: string(v[3]),
   110  	}
   111  	if len(v) > 4 && v[4] != nil {
   112  		err := json.Unmarshal(v[4], &instruction.Value)
   113  		if err != nil {
   114  			return instruction, isHint, err
   115  		}
   116  	}
   117  	return instruction, isHint, nil
   118  }