Skip to content

Commit

Permalink
Add IsNil() (#2340)
Browse files Browse the repository at this point in the history
IsNil() checks if the underlying value of the interface is nil.
  • Loading branch information
IronGauntlets authored Dec 19, 2024
1 parent e55aa34 commit eb1f2ca
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
6 changes: 2 additions & 4 deletions adapters/p2p2core/felt.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package p2p2core

import (
"encoding/binary"
"reflect"

"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/juno/p2p/starknet/spec"
"github.com/NethermindEth/juno/utils"
"github.com/ethereum/go-ethereum/common"
)

Expand All @@ -26,9 +26,7 @@ func AdaptFelt(f *spec.Felt252) *felt.Felt {
}

func adapt(v interface{ GetElements() []byte }) *felt.Felt {
// when passing a nil pointer `v` is boxed to an interface and is not nil
// see: https://blog.devtrovert.com/p/go-secret-interface-nil-is-not-nil
if v == nil || reflect.ValueOf(v).IsNil() {
if utils.IsNil(v) {
return nil
}

Expand Down
34 changes: 34 additions & 0 deletions utils/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package utils

import "reflect"

// IsNil checks if the underlying value of the interface is nil.
//
// In Golang, an interface is boxed by an underlying type and value; both of them need to be nil for the interface to be
// nil. See the following examples:
//
// var i interface{}
// fmt.Println(i == nil) // true
//
// var p *int
// var i interface{} = p
// fmt.Println(i == nil) // false!
//
// A solution for this is to use i == nil || reflect.ValueOf(i).IsNil()), however, this can cause a panic as not all
// reflect.Value has IsNil() defined. Therefore, default is to return false. For example, reflect.Array cannot be nil,
// hence calling IsNil() will cause a panic.
func IsNil(i interface{}) bool {
if i == nil {
return true
}

v := reflect.ValueOf(i)
k := v.Kind()

switch k {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
return v.IsNil()
default:
return false
}
}
21 changes: 21 additions & 0 deletions utils/check_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package utils

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestIsNil(t *testing.T) {
t.Run("both interface's type and value are nil", func(t *testing.T) {
var i interface{}
// assert.Nil() is not used to avoid assert package from using reflection
assert.True(t, IsNil(i))
})
t.Run("only interface's value is nil", func(t *testing.T) {
var arr []int
var i interface{} = arr
// assert.Nil() is not used to avoid assert package from using reflection
assert.True(t, IsNil(i))
})
}

0 comments on commit eb1f2ca

Please sign in to comment.