github.com/abemedia/go-don@v0.2.2-0.20240329015135-be88e32bb73b/decoder/decode.go (about)

     1  package decoder
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"sync"
     7  )
     8  
     9  var (
    10  	ErrUnsupportedType = errors.New("decoder: unsupported type")
    11  	ErrTagNotFound     = errors.New("decoder: tag not found")
    12  )
    13  
    14  type Getter interface {
    15  	Get(key string) string
    16  	Values(key string) []string
    17  }
    18  
    19  type Decoder struct {
    20  	tag   string
    21  	cache sync.Map
    22  }
    23  
    24  func New(tag string) *Decoder {
    25  	return &Decoder{tag: tag}
    26  }
    27  
    28  func (d *Decoder) Decode(data Getter, v any) error {
    29  	val := reflect.ValueOf(v)
    30  	if val.Kind() != reflect.Pointer {
    31  		return ErrUnsupportedType
    32  	}
    33  
    34  	val = val.Elem()
    35  	if val.Kind() != reflect.Struct {
    36  		return ErrUnsupportedType
    37  	}
    38  
    39  	t := val.Type()
    40  
    41  	dec, ok := d.cache.Load(t)
    42  	if !ok {
    43  		var err error
    44  		dec, err = compile(t, d.tag, t.Kind() == reflect.Ptr)
    45  		if err != nil {
    46  			if err != ErrTagNotFound { //nolint:errorlint,goerr113
    47  				return err
    48  			}
    49  			dec = noopDecoder
    50  		}
    51  
    52  		d.cache.Store(t, dec)
    53  	}
    54  
    55  	return dec.(decoder)(val, data) //nolint:forcetypeassert
    56  }
    57  
    58  type CachedDecoder[V any] struct {
    59  	dec decoder
    60  }
    61  
    62  func NewCached[V any](v V, tag string) (*CachedDecoder[V], error) {
    63  	t := reflect.TypeOf(v)
    64  	if t == nil {
    65  		return nil, ErrUnsupportedType
    66  	}
    67  
    68  	t, k, ptr := typeKind(t)
    69  	if k != reflect.Struct {
    70  		return nil, ErrUnsupportedType
    71  	}
    72  
    73  	dec, err := compile(t, tag, ptr)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	return &CachedDecoder[V]{dec}, nil
    79  }
    80  
    81  func (d *CachedDecoder[V]) Decode(data Getter, v *V) error {
    82  	return d.dec(reflect.ValueOf(v).Elem(), data)
    83  }
    84  
    85  func (d *CachedDecoder[V]) DecodeValue(data Getter, v reflect.Value) error {
    86  	return d.dec(v, data)
    87  }