Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate functions to convert dyn.Value to native types #1100

Merged
merged 2 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 0 additions & 50 deletions libs/dyn/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package dyn

import (
"fmt"
"time"
)

type Value struct {
Expand Down Expand Up @@ -38,11 +37,6 @@ func NewValue(v any, loc Location) Value {
}
}

func (v Value) AsMap() (map[string]Value, bool) {
m, ok := v.v.(map[string]Value)
return m, ok
}

func (v Value) Kind() Kind {
return v.k
}
Expand Down Expand Up @@ -131,47 +125,3 @@ func (v Value) MarkAnchor() Value {
func (v Value) IsAnchor() bool {
return v.anchor
}

func (v Value) MustMap() map[string]Value {
return v.v.(map[string]Value)
}

func (v Value) MustSequence() []Value {
return v.v.([]Value)
}

func (v Value) MustString() string {
return v.v.(string)
}

func (v Value) MustBool() bool {
return v.v.(bool)
}

func (v Value) MustInt() int64 {
switch vv := v.v.(type) {
case int:
return int64(vv)
case int32:
return int64(vv)
case int64:
return int64(vv)
default:
panic("not an int")
}
}

func (v Value) MustFloat() float64 {
switch vv := v.v.(type) {
case float32:
return float64(vv)
case float64:
return float64(vv)
default:
panic("not a float")
}
}

func (v Value) MustTime() time.Time {
return v.v.(time.Time)
}
139 changes: 139 additions & 0 deletions libs/dyn/value_underlying.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package dyn

import (
"fmt"
"time"
)

// AsMap returns the underlying map if this value is a map,
// the zero value and false otherwise.
func (v Value) AsMap() (map[string]Value, bool) {
vv, ok := v.v.(map[string]Value)
return vv, ok
}

// MustMap returns the underlying map if this value is a map,
// panics otherwise.
func (v Value) MustMap() map[string]Value {
vv, ok := v.AsMap()
if !ok || v.k != KindMap {
panic(fmt.Sprintf("expected kind %s, got %s", KindMap, v.k))
}
return vv
}

// AsSequence returns the underlying sequence if this value is a sequence,
// the zero value and false otherwise.
func (v Value) AsSequence() ([]Value, bool) {
vv, ok := v.v.([]Value)
return vv, ok
}

// MustSequence returns the underlying sequence if this value is a sequence,
// panics otherwise.
func (v Value) MustSequence() []Value {
vv, ok := v.AsSequence()
if !ok || v.k != KindSequence {
panic(fmt.Sprintf("expected kind %s, got %s", KindSequence, v.k))
}
return vv
}

// AsString returns the underlying string if this value is a string,
// the zero value and false otherwise.
func (v Value) AsString() (string, bool) {
vv, ok := v.v.(string)
return vv, ok
}

// MustString returns the underlying string if this value is a string,
// panics otherwise.
func (v Value) MustString() string {
vv, ok := v.AsString()
if !ok || v.k != KindString {
panic(fmt.Sprintf("expected kind %s, got %s", KindString, v.k))
}
return vv
}

// AsBool returns the underlying bool if this value is a bool,
// the zero value and false otherwise.
func (v Value) AsBool() (bool, bool) {
vv, ok := v.v.(bool)
return vv, ok
}

// MustBool returns the underlying bool if this value is a bool,
// panics otherwise.
func (v Value) MustBool() bool {
vv, ok := v.AsBool()
if !ok || v.k != KindBool {
panic(fmt.Sprintf("expected kind %s, got %s", KindBool, v.k))
}
return vv
}

// AsInt returns the underlying int if this value is an int,
// the zero value and false otherwise.
func (v Value) AsInt() (int64, bool) {
switch vv := v.v.(type) {
case int:
return int64(vv), true
case int32:
return int64(vv), true
case int64:
return int64(vv), true
default:
return 0, false
}
}

// MustInt returns the underlying int if this value is an int,
// panics otherwise.
func (v Value) MustInt() int64 {
vv, ok := v.AsInt()
if !ok || v.k != KindInt {
panic(fmt.Sprintf("expected kind %s, got %s", KindInt, v.k))
}
return vv
}

// AsFloat returns the underlying float if this value is a float,
// the zero value and false otherwise.
func (v Value) AsFloat() (float64, bool) {
switch vv := v.v.(type) {
case float32:
return float64(vv), true
case float64:
return float64(vv), true
default:
return 0, false
}
}

// MustFloat returns the underlying float if this value is a float,
// panics otherwise.
func (v Value) MustFloat() float64 {
vv, ok := v.AsFloat()
if !ok || v.k != KindFloat {
panic(fmt.Sprintf("expected kind %s, got %s", KindFloat, v.k))
}
return vv
}

// AsTime returns the underlying time if this value is a time,
// the zero value and false otherwise.
func (v Value) AsTime() (time.Time, bool) {
vv, ok := v.v.(time.Time)
return vv, ok
}

// MustTime returns the underlying time if this value is a time,
// panics otherwise.
func (v Value) MustTime() time.Time {
vv, ok := v.AsTime()
if !ok || v.k != KindTime {
panic(fmt.Sprintf("expected kind %s, got %s", KindTime, v.k))
}
return vv
}
161 changes: 161 additions & 0 deletions libs/dyn/value_underlying_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package dyn_test

import (
"testing"
"time"

"github.com/databricks/cli/libs/dyn"
"github.com/stretchr/testify/assert"
)

func TestValueUnderlyingMap(t *testing.T) {
v := dyn.V(
map[string]dyn.Value{
"key": dyn.NewValue("value", dyn.Location{File: "file", Line: 1, Column: 2}),
},
)

vv1, ok := v.AsMap()
assert.True(t, ok)

_, ok = dyn.NilValue.AsMap()
assert.False(t, ok)

vv2 := v.MustMap()
assert.Equal(t, vv1, vv2)

// Test panic.
assert.PanicsWithValue(t, "expected kind map, got nil", func() {
dyn.NilValue.MustMap()
})
}

func TestValueUnderlyingSequence(t *testing.T) {
v := dyn.V(
[]dyn.Value{
dyn.NewValue("value", dyn.Location{File: "file", Line: 1, Column: 2}),
},
)

vv1, ok := v.AsSequence()
assert.True(t, ok)

_, ok = dyn.NilValue.AsSequence()
assert.False(t, ok)

vv2 := v.MustSequence()
assert.Equal(t, vv1, vv2)

// Test panic.
assert.PanicsWithValue(t, "expected kind sequence, got nil", func() {
dyn.NilValue.MustSequence()
})
}

func TestValueUnderlyingString(t *testing.T) {
v := dyn.V("value")

vv1, ok := v.AsString()
assert.True(t, ok)

_, ok = dyn.NilValue.AsString()
assert.False(t, ok)

vv2 := v.MustString()
assert.Equal(t, vv1, vv2)

// Test panic.
assert.PanicsWithValue(t, "expected kind string, got nil", func() {
dyn.NilValue.MustString()
})
}

func TestValueUnderlyingBool(t *testing.T) {
v := dyn.V(true)

vv1, ok := v.AsBool()
assert.True(t, ok)

_, ok = dyn.NilValue.AsBool()
assert.False(t, ok)

vv2 := v.MustBool()
assert.Equal(t, vv1, vv2)

// Test panic.
assert.PanicsWithValue(t, "expected kind bool, got nil", func() {
dyn.NilValue.MustBool()
})
}

func TestValueUnderlyingInt(t *testing.T) {
v := dyn.V(int(1))

vv1, ok := v.AsInt()
assert.True(t, ok)

_, ok = dyn.NilValue.AsInt()
assert.False(t, ok)

vv2 := v.MustInt()
assert.Equal(t, vv1, vv2)

// Test panic.
assert.PanicsWithValue(t, "expected kind int, got nil", func() {
dyn.NilValue.MustInt()
})

// Test int32 type specifically.
v = dyn.V(int32(1))
vv1, ok = v.AsInt()
assert.True(t, ok)
assert.Equal(t, int64(1), vv1)

// Test int64 type specifically.
v = dyn.V(int64(1))
vv1, ok = v.AsInt()
assert.True(t, ok)
assert.Equal(t, int64(1), vv1)
}

func TestValueUnderlyingFloat(t *testing.T) {
v := dyn.V(float32(1.0))

vv1, ok := v.AsFloat()
assert.True(t, ok)

_, ok = dyn.NilValue.AsFloat()
assert.False(t, ok)

vv2 := v.MustFloat()
assert.Equal(t, vv1, vv2)

// Test panic.
assert.PanicsWithValue(t, "expected kind float, got nil", func() {
dyn.NilValue.MustFloat()
})

// Test float64 type specifically.
v = dyn.V(float64(1.0))
vv1, ok = v.AsFloat()
assert.True(t, ok)
assert.Equal(t, float64(1.0), vv1)
}

func TestValueUnderlyingTime(t *testing.T) {
v := dyn.V(time.Now())

vv1, ok := v.AsTime()
assert.True(t, ok)

_, ok = dyn.NilValue.AsTime()
assert.False(t, ok)

vv2 := v.MustTime()
assert.Equal(t, vv1, vv2)

// Test panic.
assert.PanicsWithValue(t, "expected kind time, got nil", func() {
dyn.NilValue.MustTime()
})
}
Loading