1
1
mirror of https://github.com/mcuadros/ascode synced 2024-11-23 01:11:59 +01:00

starlark/types: Values O(1)

Signed-off-by: Máximo Cuadros <mcuadros@gmail.com>
This commit is contained in:
Máximo Cuadros 2019-07-28 01:02:21 +02:00
parent 8f414b66be
commit 4ea887a849
3 changed files with 56 additions and 34 deletions

@ -3,7 +3,6 @@ package types
import (
"fmt"
"math/rand"
"sort"
"time"
"github.com/hashicorp/terraform/configs/configschema"
@ -38,7 +37,7 @@ type Resource struct {
typ string
kind Kind
block *configschema.Block
values Values
values *Values
parent *Resource
dependenies []*Resource
@ -53,6 +52,7 @@ func MakeResource(name, typ string, k Kind, b *configschema.Block, parent *Resou
typ: typ,
kind: k,
block: b,
values: NewValues(),
parent: parent,
}
}
@ -222,22 +222,22 @@ func (r *Resource) setFieldFromNestedBlock(name string, b *configschema.NestedBl
}
func (r *Resource) toDict() *starlark.Dict {
sort.Sort(r.values)
d := starlark.NewDict(len(r.values))
d := starlark.NewDict(r.values.Len())
for _, e := range r.values {
r.values.ForEach(func(e *NamedValue) error {
if r, ok := e.Starlark().(*Resource); ok {
d.SetKey(starlark.String(e.Name), r.toDict())
continue
return nil
}
if r, ok := e.Starlark().(*ResourceCollection); ok {
d.SetKey(starlark.String(e.Name), r.toDict())
continue
return nil
}
d.SetKey(starlark.String(e.Name), e.Starlark())
}
return nil
})
return d
}
@ -296,11 +296,11 @@ func (x *Resource) doCompareSameType(y *Resource, depth int) (bool, error) {
return false, nil
}
if len(x.values) != len(y.values) {
if x.values.Len() != y.values.Len() {
return false, nil
}
for _, xval := range x.values {
for _, xval := range x.values.List() {
yval := y.values.Get(xval.Name)
if yval == nil {
return false, nil

@ -119,6 +119,7 @@ func (v *Value) Interface() interface{} {
}
}
// Hash honors the starlark.Value interface.
func (v *Value) Hash() (uint32, error) {
switch value := v.v.(type) {
case *starlark.List:
@ -145,32 +146,39 @@ type NamedValue struct {
}
// Values is a list of NamedValues.
type Values []*NamedValue
type Values struct {
names sort.StringSlice
values map[string]*NamedValue
}
// NewValues return a new instance of Values
func NewValues() *Values {
return &Values{values: make(map[string]*NamedValue)}
}
// Set sets a name and a value and returns it as a NamedValue.
func (a *Values) Set(name string, v *Value) *NamedValue {
e := a.Get(name)
if e != nil {
if e, ok := a.values[name]; ok {
e.Value = v
return e
}
e = &NamedValue{Name: name, Value: v}
*a = append(*a, e)
e := &NamedValue{Name: name, Value: v}
a.values[name] = e
a.names = append(a.names, name)
return e
}
// Has returns true if Values contains a NamedValue with this name.
func (a Values) Has(name string) bool {
return a.Get(name) != nil
_, ok := a.values[name]
return ok
}
// Get returns the NamedValue with the given name, if any.
func (a Values) Get(name string) *NamedValue {
for _, e := range a {
if e.Name == name {
return e
}
if e, ok := a.values[name]; ok {
return e
}
return nil
@ -203,18 +211,19 @@ func (a Values) Hash() (uint32, error) {
// ToStringDict adds a name/value entry to d for each field of the struct.
func (a Values) ToStringDict(d starlark.StringDict) {
for _, e := range a {
d[e.Name] = e.Starlark()
sort.Sort(a.names) // we sort the list before hash it.
for _, name := range a.names {
d[name] = a.values[name].Starlark()
}
}
// ForEach call cb for each value on Values, it stop the iteration an error
// is returned.
func (a Values) ForEach(cb func(*NamedValue) error) error {
sort.Sort(a) // we sort the list before hash it.
sort.Sort(a.names) // we sort the list before hash it.
for _, v := range a {
if err := cb(v); err != nil {
for _, name := range a.names {
if err := cb(a.values[name]); err != nil {
return err
}
}
@ -222,6 +231,19 @@ func (a Values) ForEach(cb func(*NamedValue) error) error {
return nil
}
func (a Values) Len() int { return len(a) }
func (a Values) Less(i, j int) bool { return a[i].Name < a[j].Name }
func (a Values) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
// List return a list of NamedValues sorted by name.
func (a Values) List() []*NamedValue {
sort.Sort(a.names) // we sort the list before hash it.
list := make([]*NamedValue, len(a.names))
for i, name := range a.names {
list[i] = a.values[name]
}
return list
}
// Len return the length.
func (a Values) Len() int {
return len(a.values)
}

@ -68,7 +68,7 @@ func TestMustValue(t *testing.T) {
}
func TestValuesSet(t *testing.T) {
var values Values
values := NewValues()
val := values.Set("foo", MustValue(starlark.MakeInt(42)))
assert.Equal(t, val.Name, "foo")
@ -79,7 +79,7 @@ func TestValuesSet(t *testing.T) {
}
func TestValuesGet(t *testing.T) {
var values Values
values := NewValues()
values.Set("foo", MustValue(starlark.MakeInt(42)))
values.Set("foo", MustValue(starlark.MakeInt(42*2)))
@ -94,7 +94,7 @@ func TestValuesGet(t *testing.T) {
}
func TestValuesHash(t *testing.T) {
var a Values
a := NewValues()
a.Set("foo", MustValue(starlark.MakeInt(42)))
a.Set("bar", MustValue(starlark.MakeInt(42*32)))
@ -102,7 +102,7 @@ func TestValuesHash(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, hashA, uint32(0xfede4ab3))
var b Values
b := NewValues()
b.Set("bar", MustValue(starlark.MakeInt(42*32)))
b.Set("foo", MustValue(starlark.MakeInt(42)))
@ -112,7 +112,7 @@ func TestValuesHash(t *testing.T) {
}
func TestValuesToStringDict(t *testing.T) {
var a Values
a := NewValues()
a.Set("foo", MustValue(starlark.MakeInt(42)))
a.Set("bar", MustValue(starlark.MakeInt(42*32)))
@ -123,7 +123,7 @@ func TestValuesToStringDict(t *testing.T) {
}
func TestValuesForEach(t *testing.T) {
var a Values
a := NewValues()
a.Set("foo", MustValue(starlark.MakeInt(42)))
a.Set("bar", MustValue(starlark.MakeInt(42*32)))