// 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 (
	
	
	
)

const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const

// 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.
	typ *rtype

	// 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
}

// pointer returns the underlying pointer represented by v.
// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer
func ( Value) () unsafe.Pointer {
	if .typ.size != 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) interface{} {
	 := .typ
	var  interface{}
	 := (*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( interface{}) 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  *rtype
	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(), 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 Ptr.
// It returns the zero Value if v is nil.
func ( Value) () Value {
	 := .kind()
	switch  {
	case Interface:
		var  interface{}
		if .typ.NumMethod() == 0 {
			 = *(*interface{})(.ptr)
		} else {
			 = (interface{})(*(*interface {
				()
			})(.ptr))
		}
		 := unpackEface()
		if .flag != 0 {
			.flag |= .flag.ro()
		}
		return 
	case Ptr:
		 := .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) interface{} {
	if .flag == 0 {
		panic(&ValueError{"reflectlite.Value.Interface", 0})
	}

	if .kind() == 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 *(*interface{})(.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 Chan, Func, Map, Ptr, UnsafePointer:
		// if v.flag&flagMethod != 0 {
		// 	return false
		// }
		 := .ptr
		if .flag&flagIndir != 0 {
			 = *(*unsafe.Pointer)()
		}
		return  == nil
	case Interface, 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:
func chanlen(unsafe.Pointer) int
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 Array:
		 := (*arrayType)(unsafe.Pointer(.typ))
		return int(.len)
	case Chan:
		return chanlen(.pointer())
	case Map:
		return maplen(.pointer())
	case Slice:
		// Slice is bigger than a word; assume flagIndir.
		return (*unsafeheader.Slice)(.ptr).Len
	case 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", 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() == 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", Invalid})
	}
	// Method values not supported.
	return .typ
}

/*
 * constructors
 */

// implemented in package runtime
func unsafe_New(*rtype) unsafe.Pointer

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

	// TODO: Maybe allow contents of a Value to live on the stack.
	// For now we make the contents always escape to the heap. It
	// makes life easier in a few places (see chanrecv/mapassign
	// comment below).
	escapes()

	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,  *rtype,  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() == 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(Interface)}
		}
		 := valueInterface()
		if .NumMethod() == 0 {
			*(*interface{})() = 
		} else {
			ifaceE2I(, , )
		}
		return Value{, , flagIndir | flag(Interface)}
	}

	// Failed.
	panic( + ": value of type " + .typ.String() + " is not assignable to type " + .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( *rtype,  interface{},  unsafe.Pointer)

// typedmemmove copies a value of type t to dst from src.
//go:noescape
func typedmemmove( *rtype, ,  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( interface{}) {
	if dummy.b {
		dummy.x = 
	}
}

var dummy struct {
	b bool
	x interface{}
}