// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package reflectlite

import (
	
	
	
	
	
)

// Value is the reflection interface to a Go value.
//
// Not all methods apply to all kinds of values. Restrictions,
// if any, are noted in the documentation for each method.
// Use the Kind method to find out the kind of value before
// calling kind-specific methods. Calling a method
// inappropriate to the kind of type causes a run time panic.
//
// The zero Value represents no value.
// Its IsValid method returns false, its Kind method returns Invalid,
// its String method returns "<invalid Value>", and all other methods panic.
// Most functions and methods never return an invalid value.
// If one does, its documentation states the conditions explicitly.
//
// A Value can be used concurrently by multiple goroutines provided that
// the underlying Go value can be used concurrently for the equivalent
// direct operations.
//
// To compare two Values, compare the results of the Interface method.
// Using == on two Values does not compare the underlying values
// they represent.
type Value struct {
	// typ_ holds the type of the value represented by a Value.
	// Access using the typ method to avoid escape of v.
	typ_ *abi.Type

	// Pointer-valued data or, if flagIndir is set, pointer to data.
	// Valid when either flagIndir is set or typ.pointers() is true.
	ptr unsafe.Pointer

	// flag holds metadata about the value.
	// The lowest bits are flag bits:
	//	- flagStickyRO: obtained via unexported not embedded field, so read-only
	//	- flagEmbedRO: obtained via unexported embedded field, so read-only
	//	- flagIndir: val holds a pointer to the data
	//	- flagAddr: v.CanAddr is true (implies flagIndir)
	// Value cannot represent method values.
	// The next five bits give the Kind of the value.
	// This repeats typ.Kind() except for method values.
	// The remaining 23+ bits give a method number for method values.
	// If flag.kind() != Func, code can assume that flagMethod is unset.
	// If ifaceIndir(typ), code can assume that flagIndir is set.
	flag

	// A method value represents a curried method invocation
	// like r.Read for some receiver r. The typ+val+flag bits describe
	// the receiver r, but the flag's Kind bits say Func (methods are
	// functions), and the top bits of the flag give the method number
	// in r's type's method table.
}

type flag uintptr

const (
	flagKindWidth        = 5 // there are 27 kinds
	flagKindMask    flag = 1<<flagKindWidth - 1
	flagStickyRO    flag = 1 << 5
	flagEmbedRO     flag = 1 << 6
	flagIndir       flag = 1 << 7
	flagAddr        flag = 1 << 8
	flagMethod      flag = 1 << 9
	flagMethodShift      = 10
	flagRO          flag = flagStickyRO | flagEmbedRO
)

func ( flag) () Kind {
	return Kind( & flagKindMask)
}

func ( flag) () flag {
	if &flagRO != 0 {
		return flagStickyRO
	}
	return 0
}

func ( Value) () *abi.Type {
	// Types are either static (for compiler-created types) or
	// heap-allocated but always reachable (for reflection-created
	// types, held in the central map). So there is no need to
	// escape types. noescape here help avoid unnecessary escape
	// of v.
	return (*abi.Type)(noescape(unsafe.Pointer(.typ_)))
}

// pointer returns the underlying pointer represented by v.
// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
func ( Value) () unsafe.Pointer {
	if .typ().Size() != goarch.PtrSize || !.typ().Pointers() {
		panic("can't call pointer on a non-pointer Value")
	}
	if .flag&flagIndir != 0 {
		return *(*unsafe.Pointer)(.ptr)
	}
	return .ptr
}

// packEface converts v to the empty interface.
func packEface( Value) any {
	 := .typ()
	var  any
	 := (*emptyInterface)(unsafe.Pointer(&))
	// First, fill in the data portion of the interface.
	switch {
	case ifaceIndir():
		if .flag&flagIndir == 0 {
			panic("bad indir")
		}
		// Value is indirect, and so is the interface we're making.
		 := .ptr
		if .flag&flagAddr != 0 {
			// TODO: pass safe boolean from valueInterface so
			// we don't need to copy if safe==true?
			 := unsafe_New()
			typedmemmove(, , )
			 = 
		}
		.word = 
	case .flag&flagIndir != 0:
		// Value is indirect, but interface is direct. We need
		// to load the data at v.ptr into the interface data word.
		.word = *(*unsafe.Pointer)(.ptr)
	default:
		// Value is direct, and so is the interface.
		.word = .ptr
	}
	// Now, fill in the type portion. We're very careful here not
	// to have any operation between the e.word and e.typ assignments
	// that would let the garbage collector observe the partially-built
	// interface value.
	.typ = 
	return 
}

// unpackEface converts the empty interface i to a Value.
func unpackEface( any) Value {
	 := (*emptyInterface)(unsafe.Pointer(&))
	// NOTE: don't read e.word until we know whether it is really a pointer or not.
	 := .typ
	if  == nil {
		return Value{}
	}
	 := flag(.Kind())
	if ifaceIndir() {
		 |= flagIndir
	}
	return Value{, .word, }
}

// A ValueError occurs when a Value method is invoked on
// a Value that does not support it. Such cases are documented
// in the description of each method.
type ValueError struct {
	Method string
	Kind   Kind
}

func ( *ValueError) () string {
	if .Kind == 0 {
		return "reflect: call of " + .Method + " on zero Value"
	}
	return "reflect: call of " + .Method + " on " + .Kind.String() + " Value"
}

// methodName returns the name of the calling method,
// assumed to be two stack frames above.
func methodName() string {
	, , ,  := runtime.Caller(2)
	 := runtime.FuncForPC()
	if  == nil {
		return "unknown method"
	}
	return .Name()
}

// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
	typ  *abi.Type
	word unsafe.Pointer
}

// mustBeExported panics if f records that the value was obtained using
// an unexported field.
func ( flag) () {
	if  == 0 {
		panic(&ValueError{methodName(), 0})
	}
	if &flagRO != 0 {
		panic("reflect: " + methodName() + " using value obtained using unexported field")
	}
}

// mustBeAssignable panics if f records that the value is not assignable,
// which is to say that either it was obtained using an unexported field
// or it is not addressable.
func ( flag) () {
	if  == 0 {
		panic(&ValueError{methodName(), abi.Invalid})
	}
	// Assignable if addressable and not read-only.
	if &flagRO != 0 {
		panic("reflect: " + methodName() + " using value obtained using unexported field")
	}
	if &flagAddr == 0 {
		panic("reflect: " + methodName() + " using unaddressable value")
	}
}

// CanSet reports whether the value of v can be changed.
// A Value can be changed only if it is addressable and was not
// obtained by the use of unexported struct fields.
// If CanSet returns false, calling Set or any type-specific
// setter (e.g., SetBool, SetInt) will panic.
func ( Value) () bool {
	return .flag&(flagAddr|flagRO) == flagAddr
}

// Elem returns the value that the interface v contains
// or that the pointer v points to.
// It panics if v's Kind is not Interface or Pointer.
// It returns the zero Value if v is nil.
func ( Value) () Value {
	 := .kind()
	switch  {
	case abi.Interface:
		var  any
		if .typ().NumMethod() == 0 {
			 = *(*any)(.ptr)
		} else {
			 = (any)(*(*interface {
				()
			})(.ptr))
		}
		 := unpackEface()
		if .flag != 0 {
			.flag |= .flag.ro()
		}
		return 
	case abi.Pointer:
		 := .ptr
		if .flag&flagIndir != 0 {
			 = *(*unsafe.Pointer)()
		}
		// The returned value's address is v's value.
		if  == nil {
			return Value{}
		}
		 := (*ptrType)(unsafe.Pointer(.typ()))
		 := .Elem
		 := .flag&flagRO | flagIndir | flagAddr
		 |= flag(.Kind())
		return Value{, , }
	}
	panic(&ValueError{"reflectlite.Value.Elem", .kind()})
}

func valueInterface( Value) any {
	if .flag == 0 {
		panic(&ValueError{"reflectlite.Value.Interface", 0})
	}

	if .kind() == abi.Interface {
		// Special case: return the element inside the interface.
		// Empty interface has one layout, all interfaces with
		// methods have a second layout.
		if .numMethod() == 0 {
			return *(*any)(.ptr)
		}
		return *(*interface {
			()
		})(.ptr)
	}

	// TODO: pass safe to packEface so we don't need to copy if safe==true?
	return packEface()
}

// IsNil reports whether its argument v is nil. The argument must be
// a chan, func, interface, map, pointer, or slice value; if it is
// not, IsNil panics. Note that IsNil is not always equivalent to a
// regular comparison with nil in Go. For example, if v was created
// by calling ValueOf with an uninitialized interface variable i,
// i==nil will be true but v.IsNil will panic as v will be the zero
// Value.
func ( Value) () bool {
	 := .kind()
	switch  {
	case abi.Chan, abi.Func, abi.Map, abi.Pointer, abi.UnsafePointer:
		// if v.flag&flagMethod != 0 {
		// 	return false
		// }
		 := .ptr
		if .flag&flagIndir != 0 {
			 = *(*unsafe.Pointer)()
		}
		return  == nil
	case abi.Interface, abi.Slice:
		// Both interface and slice are nil if first word is 0.
		// Both are always bigger than a word; assume flagIndir.
		return *(*unsafe.Pointer)(.ptr) == nil
	}
	panic(&ValueError{"reflectlite.Value.IsNil", .kind()})
}

// IsValid reports whether v represents a value.
// It returns false if v is the zero Value.
// If IsValid returns false, all other methods except String panic.
// Most functions and methods never return an invalid Value.
// If one does, its documentation states the conditions explicitly.
func ( Value) () bool {
	return .flag != 0
}

// Kind returns v's Kind.
// If v is the zero Value (IsValid returns false), Kind returns Invalid.
func ( Value) () Kind {
	return .kind()
}

// implemented in runtime:

//go:noescape
func chanlen(unsafe.Pointer) int

//go:noescape
func maplen(unsafe.Pointer) int

// Len returns v's length.
// It panics if v's Kind is not Array, Chan, Map, Slice, or String.
func ( Value) () int {
	 := .kind()
	switch  {
	case abi.Array:
		 := (*arrayType)(unsafe.Pointer(.typ()))
		return int(.Len)
	case abi.Chan:
		return chanlen(.pointer())
	case abi.Map:
		return maplen(.pointer())
	case abi.Slice:
		// Slice is bigger than a word; assume flagIndir.
		return (*unsafeheader.Slice)(.ptr).Len
	case abi.String:
		// String is bigger than a word; assume flagIndir.
		return (*unsafeheader.String)(.ptr).Len
	}
	panic(&ValueError{"reflect.Value.Len", .kind()})
}

// NumMethod returns the number of exported methods in the value's method set.
func ( Value) () int {
	if .typ() == nil {
		panic(&ValueError{"reflectlite.Value.NumMethod", abi.Invalid})
	}
	return .typ().NumMethod()
}

// Set assigns x to the value v.
// It panics if CanSet returns false.
// As in Go, x's value must be assignable to v's type.
func ( Value) ( Value) {
	.mustBeAssignable()
	.mustBeExported() // do not let unexported x leak
	var  unsafe.Pointer
	if .kind() == abi.Interface {
		 = .ptr
	}
	 = .assignTo("reflectlite.Set", .typ(), )
	if .flag&flagIndir != 0 {
		typedmemmove(.typ(), .ptr, .ptr)
	} else {
		*(*unsafe.Pointer)(.ptr) = .ptr
	}
}

// Type returns v's type.
func ( Value) () Type {
	 := .flag
	if  == 0 {
		panic(&ValueError{"reflectlite.Value.Type", abi.Invalid})
	}
	// Method values not supported.
	return toRType(.typ())
}

/*
 * constructors
 */

// implemented in package runtime

//go:noescape
func unsafe_New(*abi.Type) unsafe.Pointer

// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
func ( any) Value {
	if  == nil {
		return Value{}
	}
	return unpackEface()
}

// assignTo returns a value v that can be assigned directly to typ.
// It panics if v is not assignable to typ.
// For a conversion to an interface type, target is a suggested scratch space to use.
func ( Value) ( string,  *abi.Type,  unsafe.Pointer) Value {
	// if v.flag&flagMethod != 0 {
	// 	v = makeMethodValue(context, v)
	// }

	switch {
	case directlyAssignable(, .typ()):
		// Overwrite type so that they match.
		// Same memory layout, so no harm done.
		 := .flag&(flagAddr|flagIndir) | .flag.ro()
		 |= flag(.Kind())
		return Value{, .ptr, }

	case implements(, .typ()):
		if  == nil {
			 = unsafe_New()
		}
		if .Kind() == abi.Interface && .IsNil() {
			// A nil ReadWriter passed to nil Reader is OK,
			// but using ifaceE2I below will panic.
			// Avoid the panic by returning a nil dst (e.g., Reader) explicitly.
			return Value{, nil, flag(abi.Interface)}
		}
		 := valueInterface()
		if .NumMethod() == 0 {
			*(*any)() = 
		} else {
			ifaceE2I(, , )
		}
		return Value{, , flagIndir | flag(abi.Interface)}
	}

	// Failed.
	panic( + ": value of type " + toRType(.typ()).String() + " is not assignable to type " + toRType().String())
}

// arrayAt returns the i-th element of p,
// an array whose elements are eltSize bytes wide.
// The array pointed at by p must have at least i+1 elements:
// it is invalid (but impossible to check here) to pass i >= len,
// because then the result will point outside the array.
// whySafe must explain why i < len. (Passing "i < len" is fine;
// the benefit is to surface this assumption at the call site.)
func arrayAt( unsafe.Pointer,  int,  uintptr,  string) unsafe.Pointer {
	return add(, uintptr()*, "i < len")
}

func ifaceE2I( *abi.Type,  any,  unsafe.Pointer)

// typedmemmove copies a value of type t to dst from src.
//
//go:noescape
func typedmemmove( *abi.Type, ,  unsafe.Pointer)

// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.
func escapes( any) {
	if dummy.b {
		dummy.x = 
	}
}

var dummy struct {
	b bool
	x any
}

//go:nosplit
func noescape( unsafe.Pointer) unsafe.Pointer {
	 := uintptr()
	return unsafe.Pointer( ^ 0)
}