github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/tiltfile/encoding/starlark.go (about)

     1  package encoding
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/pkg/errors"
     9  	"go.starlark.net/starlark"
    10  )
    11  
    12  func ConvertStructuredDataToStarlark(j interface{}) (starlark.Value, error) {
    13  	switch j := j.(type) {
    14  	case bool:
    15  		return starlark.Bool(j), nil
    16  	case string:
    17  		return starlark.String(j), nil
    18  	case json.Number:
    19  		if strings.Contains(j.String(), ".") {
    20  			f, err := j.Float64()
    21  			if err != nil {
    22  				return nil, err
    23  			}
    24  			return starlark.Float(f), nil
    25  		} else {
    26  			i, err := j.Int64()
    27  			if err != nil {
    28  				return nil, err
    29  			}
    30  			return starlark.MakeInt64(i), nil
    31  		}
    32  	case int64:
    33  		return starlark.MakeInt64(j), nil
    34  	case float64:
    35  		return starlark.Float(j), nil
    36  	case []interface{}:
    37  		listOfValues := []starlark.Value{}
    38  
    39  		for _, v := range j {
    40  			convertedValue, err := ConvertStructuredDataToStarlark(v)
    41  			if err != nil {
    42  				return nil, err
    43  			}
    44  			listOfValues = append(listOfValues, convertedValue)
    45  		}
    46  
    47  		return starlark.NewList(listOfValues), nil
    48  	case map[string]interface{}:
    49  		mapOfValues := &starlark.Dict{}
    50  
    51  		for k, v := range j {
    52  			convertedValue, err := ConvertStructuredDataToStarlark(v)
    53  			if err != nil {
    54  				return nil, err
    55  			}
    56  
    57  			err = mapOfValues.SetKey(starlark.String(k), convertedValue)
    58  			if err != nil {
    59  				return nil, err
    60  			}
    61  		}
    62  
    63  		return mapOfValues, nil
    64  	case nil:
    65  		return starlark.None, nil
    66  	}
    67  
    68  	return nil, errors.New(fmt.Sprintf("Unable to convert to starlark value, unexpected type %T", j))
    69  }
    70  
    71  func convertStarlarkToStructuredData(v starlark.Value) (interface{}, error) {
    72  	switch v := v.(type) {
    73  	case starlark.Bool:
    74  		return bool(v), nil
    75  	case starlark.String:
    76  		return v.GoString(), nil
    77  	case starlark.Int:
    78  		return v.BigInt().Int64(), nil
    79  	case starlark.Float:
    80  		return float64(v), nil
    81  	case *starlark.List:
    82  		ret := []interface{}{}
    83  
    84  		it := v.Iterate()
    85  		defer it.Done()
    86  		var e starlark.Value
    87  		for it.Next(&e) {
    88  			ee, err := convertStarlarkToStructuredData(e)
    89  			if err != nil {
    90  				return nil, err
    91  			}
    92  			ret = append(ret, ee)
    93  		}
    94  		return ret, nil
    95  	case *starlark.Dict:
    96  		ret := make(map[string]interface{})
    97  		for _, t := range v.Items() {
    98  			key := t.Index(0)
    99  			kk, err := convertStarlarkToStructuredData(key)
   100  			if err != nil {
   101  				return nil, err
   102  			}
   103  
   104  			s, ok := kk.(string)
   105  			if !ok {
   106  				return nil, fmt.Errorf("only string keys are supported in maps. found key '%s' of type %T", key.String(), kk)
   107  			}
   108  
   109  			val := t.Index(1)
   110  			vv, err := convertStarlarkToStructuredData(val)
   111  			if err != nil {
   112  				return nil, err
   113  			}
   114  
   115  			ret[s] = vv
   116  		}
   117  
   118  		return ret, nil
   119  	case starlark.NoneType:
   120  		return nil, nil
   121  	}
   122  
   123  	return nil, fmt.Errorf("unable to convert from starlark value, unsupported type %T", v)
   124  }