Skip to content

bug: Marshal and Unmarshal don't support bytes #172

@HarikrishnanBalagopal

Description

@HarikrishnanBalagopal

Bug

The function Unmarshal doesn't have a case for handling the starlark.Bytes type.

starlib/util/util.go

Lines 27 to 158 in 7fb7ff9

// Unmarshal decodes a starlark.Value into it's golang counterpart
func Unmarshal(x starlark.Value) (val interface{}, err error) {
switch v := x.(type) {
case starlark.NoneType:
val = nil
case starlark.Bool:
val = v.Truth() == starlark.True
case starlark.Int:
var tmp int
err = starlark.AsInt(x, &tmp)
val = tmp
case starlark.Float:
if f, ok := starlark.AsFloat(x); !ok {
err = fmt.Errorf("couldn't parse float")
} else {
val = f
}
case starlark.String:
val = v.GoString()
case startime.Time:
val = time.Time(v)
case *starlark.Dict:
var (
dictVal starlark.Value
pval interface{}
kval interface{}
keys []interface{}
vals []interface{}
// key as interface if found one key is not a string
ki bool
)
for _, k := range v.Keys() {
dictVal, _, err = v.Get(k)
if err != nil {
return
}
pval, err = Unmarshal(dictVal)
if err != nil {
err = fmt.Errorf("unmarshaling starlark value: %w", err)
return
}
kval, err = Unmarshal(k)
if err != nil {
err = fmt.Errorf("unmarshaling starlark key: %w", err)
return
}
if _, ok := kval.(string); !ok {
// found key as not a string
ki = true
}
keys = append(keys, kval)
vals = append(vals, pval)
}
// prepare result
rs := map[string]interface{}{}
ri := map[interface{}]interface{}{}
for i, key := range keys {
// key as interface
if ki {
ri[key] = vals[i]
} else {
rs[key.(string)] = vals[i]
}
}
if ki {
val = ri // map[interface{}]interface{}
} else {
val = rs // map[string]interface{}
}
case *starlark.List:
var (
i int
listVal starlark.Value
iter = v.Iterate()
value = make([]interface{}, v.Len())
)
defer iter.Done()
for iter.Next(&listVal) {
value[i], err = Unmarshal(listVal)
if err != nil {
return
}
i++
}
val = value
case starlark.Tuple:
var (
i int
tupleVal starlark.Value
iter = v.Iterate()
value = make([]interface{}, v.Len())
)
defer iter.Done()
for iter.Next(&tupleVal) {
value[i], err = Unmarshal(tupleVal)
if err != nil {
return
}
i++
}
val = value
case *starlark.Set:
fmt.Println("errnotdone: SET")
err = fmt.Errorf("sets aren't yet supported")
case *starlarkstruct.Struct:
if _var, ok := v.Constructor().(Unmarshaler); ok {
err = _var.UnmarshalStarlark(x)
if err != nil {
err = errors.Wrapf(err, "failed marshal %q to Starlark object", v.Constructor().Type())
return
}
val = _var
} else {
err = fmt.Errorf("constructor object from *starlarkstruct.Struct not supported Marshaler to starlark object: %s", v.Constructor().Type())
}
default:
fmt.Println("errbadtype:", x.Type())
err = fmt.Errorf("unrecognized starlark type: %s", x.Type())
}
return
}

Context

$ starlark
Welcome to Starlark (go.starlark.net)
>>> bytes([1,2])
b"\x01\x02"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions