@@ -106,7 +106,7 @@ func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string, prefix
106
106
if f .typ .Kind () == reflect .Struct {
107
107
err := d .checkRequired (f .typ , src , prefix + f .alias + "." )
108
108
if err != nil {
109
- if ! f .anon {
109
+ if ! f .isAnonymous {
110
110
return err
111
111
}
112
112
// check embedded parent field.
@@ -116,7 +116,7 @@ func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string, prefix
116
116
}
117
117
}
118
118
}
119
- if f .required {
119
+ if f .isRequired {
120
120
key := f .alias
121
121
if prefix != "" {
122
122
key = prefix + key
@@ -185,7 +185,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
185
185
// Get the converter early in case there is one for a slice type.
186
186
conv := d .cache .converter (t )
187
187
m := isTextUnmarshaler (v )
188
- if conv == nil && t .Kind () == reflect .Slice && m .IsSlice {
188
+ if conv == nil && t .Kind () == reflect .Slice && m .IsSliceElement {
189
189
var items []reflect.Value
190
190
elemT := t .Elem ()
191
191
isPtrElem := elemT .Kind () == reflect .Ptr
@@ -211,7 +211,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
211
211
}
212
212
} else if m .IsValid {
213
213
u := reflect .New (elemT )
214
- if m .IsPtr {
214
+ if m .IsSliceElementPtr {
215
215
u = reflect .New (reflect .PtrTo (elemT ).Elem ())
216
216
}
217
217
if err := u .Interface ().(encoding.TextUnmarshaler ).UnmarshalText ([]byte (value )); err != nil {
@@ -222,7 +222,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
222
222
Err : err ,
223
223
}
224
224
}
225
- if m .IsPtr {
225
+ if m .IsSliceElementPtr {
226
226
items = append (items , u .Elem ().Addr ())
227
227
} else if u .Kind () == reflect .Ptr {
228
228
items = append (items , u .Elem ())
@@ -298,14 +298,27 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
298
298
}
299
299
}
300
300
} else if m .IsValid {
301
- // If the value implements the encoding.TextUnmarshaler interface
302
- // apply UnmarshalText as the converter
303
- if err := m .Unmarshaler .UnmarshalText ([]byte (val )); err != nil {
304
- return ConversionError {
305
- Key : path ,
306
- Type : t ,
307
- Index : - 1 ,
308
- Err : err ,
301
+ if m .IsPtr {
302
+ u := reflect .New (v .Type ())
303
+ if err := u .Interface ().(encoding.TextUnmarshaler ).UnmarshalText ([]byte (val )); err != nil {
304
+ return ConversionError {
305
+ Key : path ,
306
+ Type : t ,
307
+ Index : - 1 ,
308
+ Err : err ,
309
+ }
310
+ }
311
+ v .Set (reflect .Indirect (u ))
312
+ } else {
313
+ // If the value implements the encoding.TextUnmarshaler interface
314
+ // apply UnmarshalText as the converter
315
+ if err := m .Unmarshaler .UnmarshalText ([]byte (val )); err != nil {
316
+ return ConversionError {
317
+ Key : path ,
318
+ Type : t ,
319
+ Index : - 1 ,
320
+ Err : err ,
321
+ }
309
322
}
310
323
}
311
324
} else if conv := builtinConverters [t .Kind ()]; conv != nil {
@@ -326,31 +339,36 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
326
339
}
327
340
328
341
func isTextUnmarshaler (v reflect.Value ) unmarshaler {
329
-
330
342
// Create a new unmarshaller instance
331
343
m := unmarshaler {}
332
-
333
- // As the UnmarshalText function should be applied
334
- // to the pointer of the type, we convert the value to pointer.
335
- if v .CanAddr () {
336
- v = v .Addr ()
337
- }
338
344
if m .Unmarshaler , m .IsValid = v .Interface ().(encoding.TextUnmarshaler ); m .IsValid {
339
345
return m
340
346
}
347
+ // As the UnmarshalText function should be applied to the pointer of the
348
+ // type, we check that type to see if it implements the necessary
349
+ // method.
350
+ if m .Unmarshaler , m .IsValid = reflect .New (v .Type ()).Interface ().(encoding.TextUnmarshaler ); m .IsValid {
351
+ m .IsPtr = true
352
+ return m
353
+ }
341
354
342
355
// if v is []T or *[]T create new T
343
356
t := v .Type ()
344
357
if t .Kind () == reflect .Ptr {
345
358
t = t .Elem ()
346
359
}
347
360
if t .Kind () == reflect .Slice {
348
- // if t is a pointer slice, check if it implements encoding.TextUnmarshaler
349
- m .IsSlice = true
361
+ // Check if the slice implements encoding.TextUnmarshaller
362
+ if m .Unmarshaler , m .IsValid = v .Interface ().(encoding.TextUnmarshaler ); m .IsValid {
363
+ return m
364
+ }
365
+ // If t is a pointer slice, check if its elements implement
366
+ // encoding.TextUnmarshaler
367
+ m .IsSliceElement = true
350
368
if t = t .Elem (); t .Kind () == reflect .Ptr {
351
369
t = reflect .PtrTo (t .Elem ())
352
370
v = reflect .Zero (t )
353
- m .IsPtr = true
371
+ m .IsSliceElementPtr = true
354
372
m .Unmarshaler , m .IsValid = v .Interface ().(encoding.TextUnmarshaler )
355
373
return m
356
374
}
@@ -365,9 +383,18 @@ func isTextUnmarshaler(v reflect.Value) unmarshaler {
365
383
// unmarshaller contains information about a TextUnmarshaler type
366
384
type unmarshaler struct {
367
385
Unmarshaler encoding.TextUnmarshaler
368
- IsSlice bool
369
- IsPtr bool
370
- IsValid bool
386
+ // IsValid indicates whether the resolved type indicated by the other
387
+ // flags implements the encoding.TextUnmarshaler interface.
388
+ IsValid bool
389
+ // IsPtr indicates that the resolved type is the pointer of the original
390
+ // type.
391
+ IsPtr bool
392
+ // IsSliceElement indicates that the resolved type is a slice element of
393
+ // the original type.
394
+ IsSliceElement bool
395
+ // IsSliceElementPtr indicates that the resolved type is a pointer to a
396
+ // slice element of the original type.
397
+ IsSliceElementPtr bool
371
398
}
372
399
373
400
// Errors ---------------------------------------------------------------------
0 commit comments