@@ -13,6 +13,15 @@ import (
1313 "time"
1414)
1515
16+ // safeInterface safely extracts the interface value from a reflect.Value.
17+ // It returns nil if the value is not valid or is a nil interface.
18+ func safeInterface (v reflect.Value ) any {
19+ if ! v .IsValid () {
20+ return nil
21+ }
22+ return v .Interface ()
23+ }
24+
1625// typedDecodeHook takes a raw DecodeHookFunc (an any) and turns
1726// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
1827func typedDecodeHook (h DecodeHookFunc ) DecodeHookFunc {
@@ -44,10 +53,16 @@ func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Va
4453 switch f := typedDecodeHook (raw ).(type ) {
4554 case DecodeHookFuncType :
4655 return func (from reflect.Value , to reflect.Value ) (any , error ) {
56+ if ! from .IsValid () {
57+ return f (reflect .TypeOf ((* any )(nil )).Elem (), to .Type (), nil )
58+ }
4759 return f (from .Type (), to .Type (), from .Interface ())
4860 }
4961 case DecodeHookFuncKind :
5062 return func (from reflect.Value , to reflect.Value ) (any , error ) {
63+ if ! from .IsValid () {
64+ return f (reflect .Invalid , to .Kind (), nil )
65+ }
5166 return f (from .Kind (), to .Kind (), from .Interface ())
5267 }
5368 case DecodeHookFuncValue :
@@ -70,8 +85,14 @@ func DecodeHookExec(
7085) (any , error ) {
7186 switch f := typedDecodeHook (raw ).(type ) {
7287 case DecodeHookFuncType :
88+ if ! from .IsValid () {
89+ return f (reflect .TypeOf ((* any )(nil )).Elem (), to .Type (), nil )
90+ }
7391 return f (from .Type (), to .Type (), from .Interface ())
7492 case DecodeHookFuncKind :
93+ if ! from .IsValid () {
94+ return f (reflect .Invalid , to .Kind (), nil )
95+ }
7596 return f (from .Kind (), to .Kind (), from .Interface ())
7697 case DecodeHookFuncValue :
7798 return f (from , to )
@@ -92,7 +113,7 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
92113 }
93114 return func (f reflect.Value , t reflect.Value ) (any , error ) {
94115 var err error
95- data := f . Interface ( )
116+ data := safeInterface ( f )
96117
97118 newFrom := f
98119 for _ , c := range cached {
@@ -102,8 +123,11 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
102123 }
103124 if v , ok := data .(reflect.Value ); ok {
104125 newFrom = v
105- } else {
126+ } else if data != nil {
106127 newFrom = reflect .ValueOf (data )
128+ } else {
129+ // Keep newFrom as invalid (zero) Value when data is nil
130+ newFrom = reflect.Value {}
107131 }
108132 }
109133
0 commit comments