github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/core/element/element.go (about)

     1  package element
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/lmorg/murex/lang"
    10  	"github.com/lmorg/murex/lang/types"
    11  )
    12  
    13  func init() {
    14  	lang.DefineMethod("[[", element, types.Unmarshal, types.Marshal)
    15  }
    16  
    17  func element(p *lang.Process) (err error) {
    18  	defer func() {
    19  		if r := recover(); r != nil {
    20  			err = fmt.Errorf("panic caught, please report this to https://github.com/lmorg/murex/issues : %s", r)
    21  		}
    22  	}()
    23  
    24  	dt := p.Stdin.GetDataType()
    25  
    26  	if err := p.ErrIfNotAMethod(); err != nil {
    27  		return err
    28  	}
    29  
    30  	params := p.Parameters.StringArray()
    31  
    32  	switch len(params) {
    33  	case 0:
    34  		return errors.New("missing parameter. Requires nested index")
    35  
    36  	case 1:
    37  		if strings.HasSuffix(params[0], "]]") {
    38  			params[0] = params[0][0 : len(params[0])-2]
    39  		} else {
    40  			return fmt.Errorf("missing closing brackets, ` ]]`\nExpression: %s", p.Parameters.StringAll())
    41  		}
    42  
    43  	case 2:
    44  		last := len(params) - 1
    45  		if strings.HasSuffix(params[last], "]]") {
    46  			if len(params[last]) != 2 {
    47  				return errors.New("too many parameters")
    48  			}
    49  		} else {
    50  			return fmt.Errorf("missing closing brackets, ` ]]`\nExpression: %s", p.Parameters.StringAll())
    51  		}
    52  
    53  	default:
    54  		return errors.New("too many parameters")
    55  	}
    56  
    57  	obj, err := lang.UnmarshalData(p, dt)
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	obj, err = lang.ElementLookup(obj, params[0])
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	switch v := obj.(type) {
    68  	case string:
    69  		p.Stdout.SetDataType(types.String)
    70  		_, err = p.Stdout.Write([]byte(v))
    71  	case []byte:
    72  		p.Stdout.SetDataType(types.String)
    73  		_, err = p.Stdout.Write(v)
    74  	case int:
    75  		p.Stdout.SetDataType(types.Integer)
    76  		_, err = p.Stdout.Write([]byte(strconv.Itoa(v)))
    77  	case int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
    78  		p.Stdout.SetDataType(types.Integer)
    79  		_, err = fmt.Fprint(p.Stdout, v)
    80  	case float32:
    81  		p.Stdout.SetDataType(types.Float)
    82  		_, err = p.Stdout.Write([]byte(types.FloatToString(float64(v))))
    83  	case float64:
    84  		p.Stdout.SetDataType(types.Float)
    85  		_, err = p.Stdout.Write([]byte(types.FloatToString(v)))
    86  	case bool:
    87  		p.Stdout.SetDataType(types.Boolean)
    88  		if v {
    89  			_, err = p.Stdout.Write(types.TrueByte)
    90  		} else {
    91  			_, err = p.Stdout.Write(types.FalseByte)
    92  		}
    93  	default:
    94  		p.Stdout.SetDataType(dt)
    95  		b, err := lang.MarshalData(p, dt, obj)
    96  		if err != nil {
    97  			return err
    98  		}
    99  		_, err = p.Stdout.Write(b)
   100  		if err != nil {
   101  			return err
   102  		}
   103  	}
   104  
   105  	return err
   106  }