// Copyright 2021 CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cue

import (
	"bytes"
	"encoding"
	"encoding/json"
	"reflect"
	"sort"
	"strconv"
	"strings"
	"sync"
	"unicode"
	"unicode/utf8"

	"cuelang.org/go/cue/errors"
	"cuelang.org/go/internal/core/adt"
)

// Decode initializes x with Value v. If x is a struct, it will validate the
// constraints specified in the field tags.
func (v Value) Decode(x interface{}) error {
	var d decoder
	w := reflect.ValueOf(x)
	switch {
	case !reflect.Indirect(w).CanSet():
		d.addErr(errors.Newf(v.Pos(), "cannot decode into unsettable value"))

	default:
		if w.Kind() == reflect.Ptr {
			w = w.Elem()
		}
		d.decode(w, v, false)
	}
	return d.errs
}

type decoder struct {
	errs errors.Error
}

func (d *decoder) addErr(err error) {
	if err != nil {
		d.errs = errors.Append(d.errs, errors.Promote(err, ""))
	}
}

func incompleteError(v Value) errors.Error {
	return &valueError{
		v: v,
		err: &adt.Bottom{
			Code: adt.IncompleteError,
			Err: errors.Newf(v.Pos(),
				"cannot convert non-concrete value %v", v)},
	}
}

func (d *decoder) clear(x reflect.Value) {
	if x.CanSet() {
		x.Set(reflect.Zero(x.Type()))
	}
}

func (d *decoder) decode(x reflect.Value, v Value, isPtr bool) {
	if !x.IsValid() {
		d.addErr(errors.Newf(v.Pos(), "cannot decode into invalid value"))
		return
	}

	v, _ = v.Default()
	if v.v == nil {
		d.clear(x)
		return
	}

	if err := v.Err(); err != nil {
		d.addErr(err)
		return
	}

	switch x.Kind() {
	case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Interface:
		// nullable types
		if v.Null() == nil || !v.IsConcrete() {
			d.clear(x)
			return
		}

	default:
		// TODO: allow incomplete values.
		if !v.IsConcrete() {
			d.addErr(incompleteError(v))
			return
		}
	}

	ij, it, x := indirect(x, v.Null() == nil)

	if ij != nil {
		b, err := v.marshalJSON()
		d.addErr(err)
		d.addErr(ij.UnmarshalJSON(b))
		return
	}

	if it != nil {
		if kind := v.Kind(); kind == StringKind || kind == BytesKind {
			d.addErr(errors.Newf(v.Pos(),
				"cannot unmarshal %v with TextUnmarshaler", kind))
		}
		b, err := v.Bytes()
		d.addErr(err)
		d.addErr(it.UnmarshalText(b))
		return
	}

	kind := x.Kind()

	if kind == reflect.Interface {
		value := d.interfaceValue(v)
		x.Set(reflect.ValueOf(value))
		return
	}

	switch kind {
	case reflect.Ptr:
		d.decode(x.Elem(), v, true)

	case reflect.Bool:
		b, err := v.Bool()
		d.addErr(err)
		x.SetBool(b)

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		i, err := v.Int64()
		d.addErr(err)
		if x.OverflowInt(i) {
			d.addErr(errors.Newf(v.Pos(), "integer %d overflows %s", i, kind))
			break
		}
		x.SetInt(i)

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		i, err := v.Uint64()
		d.addErr(err)
		if x.OverflowUint(i) {
			d.addErr(errors.Newf(v.Pos(), "integer %d overflows %s", i, kind))
			break
		}
		x.SetUint(i)

	case reflect.Float32, reflect.Float64:
		f, err := v.Float64()
		d.addErr(err)
		if x.OverflowFloat(f) {
			d.addErr(errors.Newf(v.Pos(), "float %g overflows %s", f, kind))
			break
		}
		x.SetFloat(f)

	case reflect.String:
		s, err := v.String()
		d.addErr(err)
		x.SetString(s)

	case reflect.Array:
		d.clear(x)

		t := x.Type()
		n := x.Len()

		if t.Elem().Kind() == reflect.Uint8 && v.Kind() == BytesKind {
			b, err := v.Bytes()
			d.addErr(err)
			for i, c := range b {
				if i >= n {
					break
				}
				x.Index(i).SetUint(uint64(c))
			}
			break
		}

		var a []Value
		list, err := v.List()
		d.addErr(err)
		for list.Next() {
			a = append(a, list.Value())
		}

		for i, v := range a {
			if i >= n {
				break
			}
			d.decode(x.Index(i), v, false)
		}

	case reflect.Slice:
		t := x.Type()
		if t.Elem().Kind() == reflect.Uint8 && v.Kind() == BytesKind {
			b, err := v.Bytes()
			d.addErr(err)
			x.SetBytes(b)
			break
		}

		var a []Value
		list, err := v.List()
		d.addErr(err)
		for list.Next() {
			a = append(a, list.Value())
		}

		switch cap := x.Cap(); {
		case cap == 0, // force a non-nil list
			cap < len(a):
			x.Set(reflect.MakeSlice(t, len(a), len(a)))

		default:
			x.SetLen(len(a))
		}

		for i, v := range a {
			d.decode(x.Index(i), v, false)
		}

	case reflect.Struct:
		d.convertStruct(x, v)

	case reflect.Map:
		d.convertMap(x, v)

	default:
		d.clear(x)
	}
}

func (d *decoder) interfaceValue(v Value) (x interface{}) {
	var err error
	v, _ = v.Default()
	switch v.Kind() {
	case NullKind:
		return nil

	case BoolKind:
		x, err = v.Bool()

	case IntKind:
		if i, err := v.Int64(); err == nil {
			return int(i)
		}
		x, err = v.Int(nil)

	case FloatKind:
		x, err = v.Float64() // or big int or

	case StringKind:
		x, err = v.String()

	case BytesKind:
		x, err = v.Bytes()

	case ListKind:
		var a []interface{}
		list, err := v.List()
		d.addErr(err)
		for list.Next() {
			a = append(a, d.interfaceValue(list.Value()))
		}
		x = a

	case StructKind:
		m := map[string]interface{}{}
		iter, err := v.Fields()
		d.addErr(err)
		for iter.Next() {
			m[iter.Label()] = d.interfaceValue(iter.Value())
		}
		x = m

	default:
		err = incompleteError(v)
	}

	d.addErr(err)
	return x
}

var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()

// convertMap keeps an existing map and overwrites any entry found in v,
// keeping other preexisting entries.
func (d *decoder) convertMap(x reflect.Value, v Value) {
	// Delete existing elements
	t := x.Type()

	// Map key must either have string kind, have an integer kind,
	// or be an encoding.TextUnmarshaler.
	switch t.Key().Kind() {
	case reflect.String,
		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
	default:
		if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
			d.addErr(errors.Newf(v.Pos(), "unsupported key type %v", t.Key()))
			return
		}
	}

	if x.IsNil() {
		x.Set(reflect.MakeMap(t))
	}

	var mapElem reflect.Value

	iter, err := v.Fields()
	d.addErr(err)
	for iter.Next() {
		key := iter.Label()

		var kv reflect.Value
		kt := t.Key()
		switch {
		case reflect.PtrTo(kt).Implements(textUnmarshalerType):
			kv = reflect.New(kt)
			err := kv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(key))
			d.addErr(err)
			kv = kv.Elem()

		case kt.Kind() == reflect.String:
			kv = reflect.ValueOf(key).Convert(kt)

		default:
			switch kt.Kind() {
			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				s := string(key)
				n, err := strconv.ParseInt(s, 10, 64)
				d.addErr(err)
				if reflect.Zero(kt).OverflowInt(n) {
					d.addErr(errors.Newf(v.Pos(), "key integer %d overflows %s", n, kt))
					break
				}
				kv = reflect.ValueOf(n).Convert(kt)

			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
				s := string(key)
				n, err := strconv.ParseUint(s, 10, 64)
				d.addErr(err)
				if reflect.Zero(kt).OverflowUint(n) {
					d.addErr(errors.Newf(v.Pos(), "key integer %d overflows %s", n, kt))
					break
				}
				kv = reflect.ValueOf(n).Convert(kt)

			default:
				panic("json: Unexpected key type") // should never occur
			}
		}

		elemType := t.Elem()
		if !mapElem.IsValid() {
			mapElem = reflect.New(elemType).Elem()
		} else {
			mapElem.Set(reflect.Zero(elemType))
		}
		d.decode(mapElem, iter.Value(), false)

		if kv.IsValid() {
			x.SetMapIndex(kv, mapElem)
		}
	}
}

func (d *decoder) convertStruct(x reflect.Value, v Value) {
	t := x.Type()
	fields := cachedTypeFields(t)

	iter, err := v.Fields()
	d.addErr(err)
	for iter.Next() {

		var f *goField
		key := iter.Label()
		if i, ok := fields.nameIndex[key]; ok {
			// Found an exact name match.
			f = &fields.list[i]
		} else {
			// Fall back to the expensive case-insensitive
			// linear search.
			key := []byte(key)
			for i := range fields.list {
				ff := &fields.list[i]
				if ff.equalFold(ff.nameBytes, key) {
					f = ff
					break
				}
			}
		}

		if f == nil {
			continue
		}

		// Figure out field corresponding to key.
		subv := x
		for _, i := range f.index {
			if subv.Kind() == reflect.Ptr {
				if subv.IsNil() {
					// If a struct embeds a pointer to an unexported type,
					// it is not possible to set a newly allocated value
					// since the field is unexported.
					//
					// See https://golang.org/issue/21357
					if !subv.CanSet() {
						d.addErr(errors.Newf(v.Pos(),
							"cannot set embedded pointer to unexported struct: %v",
							subv.Type().Elem()))
						subv = reflect.Value{}
						break
					}
					subv.Set(reflect.New(subv.Type().Elem()))
				}
				subv = subv.Elem()
			}
			subv = subv.Field(i)
		}

		// TODO: make this an option
		//  else if d.disallowUnknownFields {
		// 	d.saveError(fmt.Errorf("json: unknown field %q", key))
		// }

		d.decode(subv, iter.Value(), false)
	}
}

type structFields struct {
	list      []goField
	nameIndex map[string]int
}

func isValidTag(s string) bool {
	if s == "" {
		return false
	}
	for _, c := range s {
		switch {
		case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
			// Backslash and quote chars are reserved, but
			// otherwise any punctuation chars are allowed
			// in a tag name.
		case !unicode.IsLetter(c) && !unicode.IsDigit(c):
			return false
		}
	}
	return true
}

// A field represents a single Go field found in a struct.
type goField struct {
	name      string
	nameBytes []byte                 // []byte(name)
	equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent

	nameNonEsc  string // `"` + name + `":`
	nameEscHTML string // `"` + HTMLEscape(name) + `":`

	tag       bool
	index     []int
	typ       reflect.Type
	omitEmpty bool
}

// byIndex sorts goField by index sequence.
type byIndex []goField

func (x byIndex) Len() int { return len(x) }

func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }

func (x byIndex) Less(i, j int) bool {
	for k, xik := range x[i].index {
		if k >= len(x[j].index) {
			return false
		}
		if xik != x[j].index[k] {
			return xik < x[j].index[k]
		}
	}
	return len(x[i].index) < len(x[j].index)
}

// typeFields returns a list of fields that JSON should recognize for the given type.
// The algorithm is breadth-first search over the set of structs to include - the top struct
// and then any reachable anonymous structs.
func typeFields(t reflect.Type) structFields {
	// Anonymous fields to explore at the current level and the next.
	current := []goField{}
	next := []goField{{typ: t}}

	// Count of queued names for current level and the next.
	var count, nextCount map[reflect.Type]int

	// Types already visited at an earlier level.
	visited := map[reflect.Type]bool{}

	// Fields found.
	var fields []goField

	// Buffer to run HTMLEscape on field names.
	var nameEscBuf bytes.Buffer

	for len(next) > 0 {
		current, next = next, current[:0]
		count, nextCount = nextCount, map[reflect.Type]int{}

		for _, f := range current {
			if visited[f.typ] {
				continue
			}
			visited[f.typ] = true

			// Scan f.typ for fields to include.
			for i := 0; i < f.typ.NumField(); i++ {
				sf := f.typ.Field(i)
				isUnexported := sf.PkgPath != ""
				if sf.Anonymous {
					t := sf.Type
					if t.Kind() == reflect.Ptr {
						t = t.Elem()
					}
					if isUnexported && t.Kind() != reflect.Struct {
						// Ignore embedded fields of unexported non-struct types.
						continue
					}
					// Do not ignore embedded fields of unexported struct types
					// since they may have exported fields.
				} else if isUnexported {
					// Ignore unexported non-embedded fields.
					continue
				}
				tag := sf.Tag.Get("json")
				if tag == "-" {
					continue
				}
				name, opts := parseTag(tag)
				if !isValidTag(name) {
					name = ""
				}
				index := make([]int, len(f.index)+1)
				copy(index, f.index)
				index[len(f.index)] = i

				ft := sf.Type
				if ft.Name() == "" && ft.Kind() == reflect.Ptr {
					// Follow pointer.
					ft = ft.Elem()
				}

				// Record found field and index sequence.
				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
					tagged := name != ""
					if name == "" {
						name = sf.Name
					}
					field := goField{
						name:      name,
						tag:       tagged,
						index:     index,
						typ:       ft,
						omitEmpty: opts.Contains("omitempty"),
					}
					field.nameBytes = []byte(field.name)
					field.equalFold = foldFunc(field.nameBytes)

					// Build nameEscHTML and nameNonEsc ahead of time.
					nameEscBuf.Reset()
					nameEscBuf.WriteString(`"`)
					json.HTMLEscape(&nameEscBuf, field.nameBytes)
					nameEscBuf.WriteString(`":`)
					field.nameEscHTML = nameEscBuf.String()
					field.nameNonEsc = `"` + field.name + `":`

					fields = append(fields, field)
					if count[f.typ] > 1 {
						// If there were multiple instances, add a second,
						// so that the annihilation code will see a duplicate.
						// It only cares about the distinction between 1 or 2,
						// so don't bother generating any more copies.
						fields = append(fields, fields[len(fields)-1])
					}
					continue
				}

				// Record new anonymous struct to explore in next round.
				nextCount[ft]++
				if nextCount[ft] == 1 {
					next = append(next, goField{name: ft.Name(), index: index, typ: ft})
				}
			}
		}
	}

	sort.Slice(fields, func(i, j int) bool {
		x := fields
		// sort field by name, breaking ties with depth, then
		// breaking ties with "name came from json tag", then
		// breaking ties with index sequence.
		if x[i].name != x[j].name {
			return x[i].name < x[j].name
		}
		if len(x[i].index) != len(x[j].index) {
			return len(x[i].index) < len(x[j].index)
		}
		if x[i].tag != x[j].tag {
			return x[i].tag
		}
		return byIndex(x).Less(i, j)
	})

	// Delete all fields that are hidden by the Go rules for embedded fields,
	// except that fields with JSON tags are promoted.

	// The fields are sorted in primary order of name, secondary order
	// of field index length. Loop over names; for each name, delete
	// hidden fields by choosing the one dominant field that survives.
	out := fields[:0]
	for advance, i := 0, 0; i < len(fields); i += advance {
		// One iteration per name.
		// Find the sequence of fields with the name of this first field.
		fi := fields[i]
		name := fi.name
		for advance = 1; i+advance < len(fields); advance++ {
			fj := fields[i+advance]
			if fj.name != name {
				break
			}
		}
		if advance == 1 { // Only one field with this name
			out = append(out, fi)
			continue
		}
		dominant, ok := dominantField(fields[i : i+advance])
		if ok {
			out = append(out, dominant)
		}
	}

	fields = out
	sort.Sort(byIndex(fields))

	nameIndex := make(map[string]int, len(fields))
	for i, field := range fields {
		nameIndex[field.name] = i
	}
	return structFields{fields, nameIndex}
}

// dominantField looks through the fields, all of which are known to
// have the same name, to find the single field that dominates the
// others using Go's embedding rules, modified by the presence of
// JSON tags. If there are multiple top-level fields, the boolean
// will be false: This condition is an error in Go and we skip all
// the fields.
func dominantField(fields []goField) (goField, bool) {
	// The fields are sorted in increasing index-length order, then by presence of tag.
	// That means that the first field is the dominant one. We need only check
	// for error cases: two fields at top level, either both tagged or neither tagged.
	if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
		return goField{}, false
	}
	return fields[0], true
}

var fieldCache sync.Map // map[reflect.Type]structFields

// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
func cachedTypeFields(t reflect.Type) structFields {
	if f, ok := fieldCache.Load(t); ok {
		return f.(structFields)
	}
	f, _ := fieldCache.LoadOrStore(t, typeFields(t))
	return f.(structFields)
}

// tagOptions is the string following a comma in a struct field's "json"
// tag, or the empty string. It does not include the leading comma.
type tagOptions string

// parseTag splits a struct field's json tag into its name and
// comma-separated options.
func parseTag(tag string) (string, tagOptions) {
	if idx := strings.Index(tag, ","); idx != -1 {
		return tag[:idx], tagOptions(tag[idx+1:])
	}
	return tag, tagOptions("")
}

// Contains reports whether a comma-separated list of options
// contains a particular substr flag. substr must be surrounded by a
// string boundary or commas.
func (o tagOptions) Contains(optionName string) bool {
	if len(o) == 0 {
		return false
	}
	s := string(o)
	for s != "" {
		var next string
		i := strings.Index(s, ",")
		if i >= 0 {
			s, next = s[:i], s[i+1:]
		}
		if s == optionName {
			return true
		}
		s = next
	}
	return false
}

// foldFunc returns one of four different case folding equivalence
// functions, from most general (and slow) to fastest:
//
// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
// 3) asciiEqualFold, no special, but includes non-letters (including _)
// 4) simpleLetterEqualFold, no specials, no non-letters.
//
// The letters S and K are special because they map to 3 runes, not just 2:
//  * S maps to s and to U+017F 'ſ' Latin small letter long s
//  * k maps to K and to U+212A 'K' Kelvin sign
// See https://play.golang.org/p/tTxjOc0OGo
//
// The returned function is specialized for matching against s and
// should only be given s. It's not curried for performance reasons.
func foldFunc(s []byte) func(s, t []byte) bool {
	nonLetter := false
	special := false // special letter
	for _, b := range s {
		if b >= utf8.RuneSelf {
			return bytes.EqualFold
		}
		upper := b & caseMask
		if upper < 'A' || upper > 'Z' {
			nonLetter = true
		} else if upper == 'K' || upper == 'S' {
			// See above for why these letters are special.
			special = true
		}
	}
	if special {
		return equalFoldRight
	}
	if nonLetter {
		return asciiEqualFold
	}
	return simpleLetterEqualFold
}

const (
	caseMask     = ^byte(0x20) // Mask to ignore case in ASCII.
	kelvin       = '\u212a'
	smallLongEss = '\u017f'
)

// equalFoldRight is a specialization of bytes.EqualFold when s is
// known to be all ASCII (including punctuation), but contains an 's',
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
// See comments on foldFunc.
func equalFoldRight(s, t []byte) bool {
	for _, sb := range s {
		if len(t) == 0 {
			return false
		}
		tb := t[0]
		if tb < utf8.RuneSelf {
			if sb != tb {
				sbUpper := sb & caseMask
				if 'A' <= sbUpper && sbUpper <= 'Z' {
					if sbUpper != tb&caseMask {
						return false
					}
				} else {
					return false
				}
			}
			t = t[1:]
			continue
		}
		// sb is ASCII and t is not. t must be either kelvin
		// sign or long s; sb must be s, S, k, or K.
		tr, size := utf8.DecodeRune(t)
		switch sb {
		case 's', 'S':
			if tr != smallLongEss {
				return false
			}
		case 'k', 'K':
			if tr != kelvin {
				return false
			}
		default:
			return false
		}
		t = t[size:]

	}
	if len(t) > 0 {
		return false
	}
	return true
}

// asciiEqualFold is a specialization of bytes.EqualFold for use when
// s is all ASCII (but may contain non-letters) and contains no
// special-folding letters.
// See comments on foldFunc.
func asciiEqualFold(s, t []byte) bool {
	if len(s) != len(t) {
		return false
	}
	for i, sb := range s {
		tb := t[i]
		if sb == tb {
			continue
		}
		if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
			if sb&caseMask != tb&caseMask {
				return false
			}
		} else {
			return false
		}
	}
	return true
}

// simpleLetterEqualFold is a specialization of bytes.EqualFold for
// use when s is all ASCII letters (no underscores, etc) and also
// doesn't contain 'k', 'K', 's', or 'S'.
// See comments on foldFunc.
func simpleLetterEqualFold(s, t []byte) bool {
	if len(s) != len(t) {
		return false
	}
	for i, b := range s {
		if b&caseMask != t[i]&caseMask {
			return false
		}
	}
	return true
}

// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
// If it encounters an Unmarshaler, indirect stops and returns that.
// If decodingNull is true, indirect stops at the first settable pointer so it
// can be set to nil.
func indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
	// Issue #24153 indicates that it is generally not a guaranteed property
	// that you may round-trip a reflect.Value by calling Value.Addr().Elem()
	// and expect the value to still be settable for values derived from
	// unexported embedded struct fields.
	//
	// The logic below effectively does this when it first addresses the value
	// (to satisfy possible pointer methods) and continues to dereference
	// subsequent pointers as necessary.
	//
	// After the first round-trip, we set v back to the original value to
	// preserve the original RW flags contained in reflect.Value.
	v0 := v
	haveAddr := false

	// If v is a named type and is addressable,
	// start with its address, so that if the type has pointer methods,
	// we find them.
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		haveAddr = true
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be
		// usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
				haveAddr = false
				v = e
				continue
			}
		}

		if v.Kind() != reflect.Ptr {
			break
		}

		if decodingNull && v.CanSet() {
			break
		}

		// Prevent infinite loop if v is an interface pointing to its own address:
		//     var v interface{}
		//     v = &v
		if v.Elem().Kind() == reflect.Interface && v.Elem().Elem() == v {
			v = v.Elem()
			break
		}
		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		if v.Type().NumMethod() > 0 && v.CanInterface() {
			if u, ok := v.Interface().(json.Unmarshaler); ok {
				return u, nil, reflect.Value{}
			}
			if !decodingNull {
				if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
					return nil, u, reflect.Value{}
				}
			}
		}

		if haveAddr {
			v = v0 // restore original value after round-trip Value.Addr().Elem()
			haveAddr = false
		} else {
			v = v.Elem()
		}
	}
	return nil, nil, v
}
