github.com/GuanceCloud/cliutils@v1.1.21/pipeline/ptinput/funcs/fn_delete.go (about)

     1  // Unless explicitly stated otherwise all files in this repository are licensed
     2  // under the MIT License.
     3  // This product includes software developed at Guance Cloud (https://www.guance.com/).
     4  // Copyright 2021-present Guance, Inc.
     5  
     6  package funcs
     7  
     8  import (
     9  	"fmt"
    10  
    11  	"github.com/GuanceCloud/platypus/pkg/ast"
    12  	"github.com/GuanceCloud/platypus/pkg/engine/runtime"
    13  	"github.com/GuanceCloud/platypus/pkg/errchain"
    14  	"github.com/spf13/cast"
    15  )
    16  
    17  func DeleteMapItemChecking(ctx *runtime.Task, funcExpr *ast.CallExpr) *errchain.PlError {
    18  	if err := normalizeFuncArgsDeprecated(funcExpr, []string{"src", "key"}, 2); err != nil {
    19  		return runtime.NewRunError(ctx, err.Error(), funcExpr.NamePos)
    20  	}
    21  
    22  	switch funcExpr.Param[0].NodeType { //nolint:exhaustive
    23  	case ast.TypeIndexExpr, ast.TypeIdentifier:
    24  	default:
    25  		return runtime.NewRunError(ctx, fmt.Sprintf("param key expect IndexExpr or Identifier, got %s",
    26  			funcExpr.Param[0].NodeType), funcExpr.Param[0].StartPos())
    27  	}
    28  
    29  	switch funcExpr.Param[1].NodeType { //nolint:exhaustive
    30  	case ast.TypeStringLiteral:
    31  	default:
    32  		return runtime.NewRunError(ctx, fmt.Sprintf("param key expect StringLiteral, got %s",
    33  			funcExpr.Param[1].NodeType), funcExpr.Param[1].StartPos())
    34  	}
    35  
    36  	return nil
    37  }
    38  
    39  func DeleteMapItem(ctx *runtime.Task, funcExpr *ast.CallExpr) *errchain.PlError {
    40  	var keyName string
    41  	switch funcExpr.Param[1].NodeType { //nolint:exhaustive
    42  	case ast.TypeStringLiteral:
    43  		keyName = funcExpr.Param[1].StringLiteral().Val
    44  	default:
    45  		return runtime.NewRunError(ctx, fmt.Sprintf("param key expect StringLiteral, got %s",
    46  			funcExpr.Param[1].NodeType), funcExpr.Param[1].StartPos())
    47  	}
    48  
    49  	switch funcExpr.Param[0].NodeType { //nolint:exhaustive
    50  	case ast.TypeIndexExpr:
    51  		indexExprDel(ctx, funcExpr.Param[0].IndexExpr(), keyName)
    52  		return nil
    53  	case ast.TypeIdentifier:
    54  		key, err := getKeyName(funcExpr.Param[0])
    55  		if err != nil {
    56  			return runtime.NewRunError(ctx, err.Error(), funcExpr.Param[0].StartPos())
    57  		}
    58  		varb, err := ctx.GetKey(key)
    59  		if err != nil {
    60  			l.Debugf("key `%s' not exist, ignored", key)
    61  			return nil
    62  		}
    63  
    64  		if varb.DType == ast.Map {
    65  			switch v := varb.Value.(type) {
    66  			case map[string]any: // for json map
    67  				delete(v, keyName)
    68  				return nil
    69  			default:
    70  				return nil
    71  			}
    72  		}
    73  	default:
    74  		return runtime.NewRunError(ctx, fmt.Sprintf("param key expect IndexExpr or Identifier, got %s",
    75  			funcExpr.Param[0].NodeType), funcExpr.Param[0].StartPos())
    76  	}
    77  
    78  	return nil
    79  }
    80  
    81  func indexExprDel(ctx *runtime.Task, expr *ast.IndexExpr, keyDel string) {
    82  	key := expr.Obj.Name
    83  
    84  	varb, err := ctx.GetKey(key)
    85  	if err != nil {
    86  		return
    87  	}
    88  
    89  	switch varb.DType { //nolint:exhaustive
    90  	case ast.List:
    91  		switch varb.Value.(type) {
    92  		case []any:
    93  		default:
    94  			return
    95  		}
    96  	case ast.Map:
    97  		switch varb.Value.(type) {
    98  		case map[string]any: // for json map
    99  		default:
   100  			return
   101  		}
   102  	default:
   103  		return
   104  	}
   105  
   106  	searchListAndMap(ctx, varb.Value, expr.Index, keyDel)
   107  }
   108  
   109  func searchListAndMap(ctx *runtime.Task, obj any, index []*ast.Node, keyDel string) {
   110  	cur := obj
   111  
   112  	for _, i := range index {
   113  		key, keyType, err := runtime.RunStmt(ctx, i)
   114  		if err != nil {
   115  			return
   116  		}
   117  		switch curVal := cur.(type) {
   118  		case map[string]any:
   119  			if keyType != ast.String {
   120  				return
   121  			}
   122  			var ok bool
   123  			cur, ok = curVal[key.(string)]
   124  			if !ok {
   125  				return
   126  			}
   127  		case []any:
   128  			if keyType != ast.Int {
   129  				return
   130  			}
   131  			keyInt := cast.ToInt(key)
   132  
   133  			// 反转负数
   134  			if keyInt < 0 {
   135  				keyInt = len(curVal) + keyInt
   136  			}
   137  
   138  			if keyInt < 0 || keyInt >= len(curVal) {
   139  				return
   140  			}
   141  			cur = curVal[keyInt]
   142  		default:
   143  			return
   144  		}
   145  	}
   146  
   147  	if v, ok := cur.(map[string]any); ok {
   148  		delete(v, keyDel)
   149  	}
   150  }