1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package reflectlite
6
7import (
8	"internal/abi"
9	"internal/goarch"
10	"internal/unsafeheader"
11	"runtime"
12	"unsafe"
13)
14
15// Value is the reflection interface to a Go value.
16//
17// Not all methods apply to all kinds of values. Restrictions,
18// if any, are noted in the documentation for each method.
19// Use the Kind method to find out the kind of value before
20// calling kind-specific methods. Calling a method
21// inappropriate to the kind of type causes a run time panic.
22//
23// The zero Value represents no value.
24// Its IsValid method returns false, its Kind method returns Invalid,
25// its String method returns "<invalid Value>", and all other methods panic.
26// Most functions and methods never return an invalid value.
27// If one does, its documentation states the conditions explicitly.
28//
29// A Value can be used concurrently by multiple goroutines provided that
30// the underlying Go value can be used concurrently for the equivalent
31// direct operations.
32//
33// To compare two Values, compare the results of the Interface method.
34// Using == on two Values does not compare the underlying values
35// they represent.
36type Value struct {
37	// typ_ holds the type of the value represented by a Value.
38	// Access using the typ method to avoid escape of v.
39	typ_ *abi.Type
40
41	// Pointer-valued data or, if flagIndir is set, pointer to data.
42	// Valid when either flagIndir is set or typ.pointers() is true.
43	ptr unsafe.Pointer
44
45	// flag holds metadata about the value.
46	// The lowest bits are flag bits:
47	//	- flagStickyRO: obtained via unexported not embedded field, so read-only
48	//	- flagEmbedRO: obtained via unexported embedded field, so read-only
49	//	- flagIndir: val holds a pointer to the data
50	//	- flagAddr: v.CanAddr is true (implies flagIndir)
51	// Value cannot represent method values.
52	// The next five bits give the Kind of the value.
53	// This repeats typ.Kind() except for method values.
54	// The remaining 23+ bits give a method number for method values.
55	// If flag.kind() != Func, code can assume that flagMethod is unset.
56	// If ifaceIndir(typ), code can assume that flagIndir is set.
57	flag
58
59	// A method value represents a curried method invocation
60	// like r.Read for some receiver r. The typ+val+flag bits describe
61	// the receiver r, but the flag's Kind bits say Func (methods are
62	// functions), and the top bits of the flag give the method number
63	// in r's type's method table.
64}
65
66type flag uintptr
67
68const (
69	flagKindWidth        = 5 // there are 27 kinds
70	flagKindMask    flag = 1<<flagKindWidth - 1
71	flagStickyRO    flag = 1 << 5
72	flagEmbedRO     flag = 1 << 6
73	flagIndir       flag = 1 << 7
74	flagAddr        flag = 1 << 8
75	flagMethod      flag = 1 << 9
76	flagMethodShift      = 10
77	flagRO          flag = flagStickyRO | flagEmbedRO
78)
79
80func (f flag) kind() Kind {
81	return Kind(f & flagKindMask)
82}
83
84func (f flag) ro() flag {
85	if f&flagRO != 0 {
86		return flagStickyRO
87	}
88	return 0
89}
90
91func (v Value) typ() *abi.Type {
92	// Types are either static (for compiler-created types) or
93	// heap-allocated but always reachable (for reflection-created
94	// types, held in the central map). So there is no need to
95	// escape types. noescape here help avoid unnecessary escape
96	// of v.
97	return (*abi.Type)(abi.NoEscape(unsafe.Pointer(v.typ_)))
98}
99
100// pointer returns the underlying pointer represented by v.
101// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
102func (v Value) pointer() unsafe.Pointer {
103	if v.typ().Size() != goarch.PtrSize || !v.typ().Pointers() {
104		panic("can't call pointer on a non-pointer Value")
105	}
106	if v.flag&flagIndir != 0 {
107		return *(*unsafe.Pointer)(v.ptr)
108	}
109	return v.ptr
110}
111
112// packEface converts v to the empty interface.
113func packEface(v Value) any {
114	t := v.typ()
115	var i any
116	e := (*abi.EmptyInterface)(unsafe.Pointer(&i))
117	// First, fill in the data portion of the interface.
118	switch {
119	case t.IfaceIndir():
120		if v.flag&flagIndir == 0 {
121			panic("bad indir")
122		}
123		// Value is indirect, and so is the interface we're making.
124		ptr := v.ptr
125		if v.flag&flagAddr != 0 {
126			c := unsafe_New(t)
127			typedmemmove(t, c, ptr)
128			ptr = c
129		}
130		e.Data = ptr
131	case v.flag&flagIndir != 0:
132		// Value is indirect, but interface is direct. We need
133		// to load the data at v.ptr into the interface data word.
134		e.Data = *(*unsafe.Pointer)(v.ptr)
135	default:
136		// Value is direct, and so is the interface.
137		e.Data = v.ptr
138	}
139	// Now, fill in the type portion. We're very careful here not
140	// to have any operation between the e.word and e.typ assignments
141	// that would let the garbage collector observe the partially-built
142	// interface value.
143	e.Type = t
144	return i
145}
146
147// unpackEface converts the empty interface i to a Value.
148func unpackEface(i any) Value {
149	e := (*abi.EmptyInterface)(unsafe.Pointer(&i))
150	// NOTE: don't read e.word until we know whether it is really a pointer or not.
151	t := e.Type
152	if t == nil {
153		return Value{}
154	}
155	f := flag(t.Kind())
156	if t.IfaceIndir() {
157		f |= flagIndir
158	}
159	return Value{t, e.Data, f}
160}
161
162// A ValueError occurs when a Value method is invoked on
163// a Value that does not support it. Such cases are documented
164// in the description of each method.
165type ValueError struct {
166	Method string
167	Kind   Kind
168}
169
170func (e *ValueError) Error() string {
171	if e.Kind == 0 {
172		return "reflect: call of " + e.Method + " on zero Value"
173	}
174	return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
175}
176
177// methodName returns the name of the calling method,
178// assumed to be two stack frames above.
179func methodName() string {
180	pc, _, _, _ := runtime.Caller(2)
181	f := runtime.FuncForPC(pc)
182	if f == nil {
183		return "unknown method"
184	}
185	return f.Name()
186}
187
188// mustBeExported panics if f records that the value was obtained using
189// an unexported field.
190func (f flag) mustBeExported() {
191	if f == 0 {
192		panic(&ValueError{methodName(), 0})
193	}
194	if f&flagRO != 0 {
195		panic("reflect: " + methodName() + " using value obtained using unexported field")
196	}
197}
198
199// mustBeAssignable panics if f records that the value is not assignable,
200// which is to say that either it was obtained using an unexported field
201// or it is not addressable.
202func (f flag) mustBeAssignable() {
203	if f == 0 {
204		panic(&ValueError{methodName(), abi.Invalid})
205	}
206	// Assignable if addressable and not read-only.
207	if f&flagRO != 0 {
208		panic("reflect: " + methodName() + " using value obtained using unexported field")
209	}
210	if f&flagAddr == 0 {
211		panic("reflect: " + methodName() + " using unaddressable value")
212	}
213}
214
215// CanSet reports whether the value of v can be changed.
216// A Value can be changed only if it is addressable and was not
217// obtained by the use of unexported struct fields.
218// If CanSet returns false, calling Set or any type-specific
219// setter (e.g., SetBool, SetInt) will panic.
220func (v Value) CanSet() bool {
221	return v.flag&(flagAddr|flagRO) == flagAddr
222}
223
224// Elem returns the value that the interface v contains
225// or that the pointer v points to.
226// It panics if v's Kind is not Interface or Pointer.
227// It returns the zero Value if v is nil.
228func (v Value) Elem() Value {
229	k := v.kind()
230	switch k {
231	case abi.Interface:
232		var eface any
233		if v.typ().NumMethod() == 0 {
234			eface = *(*any)(v.ptr)
235		} else {
236			eface = (any)(*(*interface {
237				M()
238			})(v.ptr))
239		}
240		x := unpackEface(eface)
241		if x.flag != 0 {
242			x.flag |= v.flag.ro()
243		}
244		return x
245	case abi.Pointer:
246		ptr := v.ptr
247		if v.flag&flagIndir != 0 {
248			ptr = *(*unsafe.Pointer)(ptr)
249		}
250		// The returned value's address is v's value.
251		if ptr == nil {
252			return Value{}
253		}
254		tt := (*ptrType)(unsafe.Pointer(v.typ()))
255		typ := tt.Elem
256		fl := v.flag&flagRO | flagIndir | flagAddr
257		fl |= flag(typ.Kind())
258		return Value{typ, ptr, fl}
259	}
260	panic(&ValueError{"reflectlite.Value.Elem", v.kind()})
261}
262
263func valueInterface(v Value) any {
264	if v.flag == 0 {
265		panic(&ValueError{"reflectlite.Value.Interface", 0})
266	}
267
268	if v.kind() == abi.Interface {
269		// Special case: return the element inside the interface.
270		// Empty interface has one layout, all interfaces with
271		// methods have a second layout.
272		if v.numMethod() == 0 {
273			return *(*any)(v.ptr)
274		}
275		return *(*interface {
276			M()
277		})(v.ptr)
278	}
279
280	return packEface(v)
281}
282
283// IsNil reports whether its argument v is nil. The argument must be
284// a chan, func, interface, map, pointer, or slice value; if it is
285// not, IsNil panics. Note that IsNil is not always equivalent to a
286// regular comparison with nil in Go. For example, if v was created
287// by calling ValueOf with an uninitialized interface variable i,
288// i==nil will be true but v.IsNil will panic as v will be the zero
289// Value.
290func (v Value) IsNil() bool {
291	k := v.kind()
292	switch k {
293	case abi.Chan, abi.Func, abi.Map, abi.Pointer, abi.UnsafePointer:
294		// if v.flag&flagMethod != 0 {
295		// 	return false
296		// }
297		ptr := v.ptr
298		if v.flag&flagIndir != 0 {
299			ptr = *(*unsafe.Pointer)(ptr)
300		}
301		return ptr == nil
302	case abi.Interface, abi.Slice:
303		// Both interface and slice are nil if first word is 0.
304		// Both are always bigger than a word; assume flagIndir.
305		return *(*unsafe.Pointer)(v.ptr) == nil
306	}
307	panic(&ValueError{"reflectlite.Value.IsNil", v.kind()})
308}
309
310// IsValid reports whether v represents a value.
311// It returns false if v is the zero Value.
312// If IsValid returns false, all other methods except String panic.
313// Most functions and methods never return an invalid Value.
314// If one does, its documentation states the conditions explicitly.
315func (v Value) IsValid() bool {
316	return v.flag != 0
317}
318
319// Kind returns v's Kind.
320// If v is the zero Value (IsValid returns false), Kind returns Invalid.
321func (v Value) Kind() Kind {
322	return v.kind()
323}
324
325// implemented in runtime:
326
327//go:noescape
328func chanlen(unsafe.Pointer) int
329
330//go:noescape
331func maplen(unsafe.Pointer) int
332
333// Len returns v's length.
334// It panics if v's Kind is not Array, Chan, Map, Slice, or String.
335func (v Value) Len() int {
336	k := v.kind()
337	switch k {
338	case abi.Array:
339		tt := (*arrayType)(unsafe.Pointer(v.typ()))
340		return int(tt.Len)
341	case abi.Chan:
342		return chanlen(v.pointer())
343	case abi.Map:
344		return maplen(v.pointer())
345	case abi.Slice:
346		// Slice is bigger than a word; assume flagIndir.
347		return (*unsafeheader.Slice)(v.ptr).Len
348	case abi.String:
349		// String is bigger than a word; assume flagIndir.
350		return (*unsafeheader.String)(v.ptr).Len
351	}
352	panic(&ValueError{"reflect.Value.Len", v.kind()})
353}
354
355// NumMethod returns the number of exported methods in the value's method set.
356func (v Value) numMethod() int {
357	if v.typ() == nil {
358		panic(&ValueError{"reflectlite.Value.NumMethod", abi.Invalid})
359	}
360	return v.typ().NumMethod()
361}
362
363// Set assigns x to the value v.
364// It panics if CanSet returns false.
365// As in Go, x's value must be assignable to v's type.
366func (v Value) Set(x Value) {
367	v.mustBeAssignable()
368	x.mustBeExported() // do not let unexported x leak
369	var target unsafe.Pointer
370	if v.kind() == abi.Interface {
371		target = v.ptr
372	}
373	x = x.assignTo("reflectlite.Set", v.typ(), target)
374	if x.flag&flagIndir != 0 {
375		typedmemmove(v.typ(), v.ptr, x.ptr)
376	} else {
377		*(*unsafe.Pointer)(v.ptr) = x.ptr
378	}
379}
380
381// Type returns v's type.
382func (v Value) Type() Type {
383	f := v.flag
384	if f == 0 {
385		panic(&ValueError{"reflectlite.Value.Type", abi.Invalid})
386	}
387	// Method values not supported.
388	return toRType(v.typ())
389}
390
391/*
392 * constructors
393 */
394
395// implemented in package runtime
396
397//go:noescape
398func unsafe_New(*abi.Type) unsafe.Pointer
399
400// ValueOf returns a new Value initialized to the concrete value
401// stored in the interface i. ValueOf(nil) returns the zero Value.
402func ValueOf(i any) Value {
403	if i == nil {
404		return Value{}
405	}
406	return unpackEface(i)
407}
408
409// assignTo returns a value v that can be assigned directly to typ.
410// It panics if v is not assignable to typ.
411// For a conversion to an interface type, target is a suggested scratch space to use.
412func (v Value) assignTo(context string, dst *abi.Type, target unsafe.Pointer) Value {
413	// if v.flag&flagMethod != 0 {
414	// 	v = makeMethodValue(context, v)
415	// }
416
417	switch {
418	case directlyAssignable(dst, v.typ()):
419		// Overwrite type so that they match.
420		// Same memory layout, so no harm done.
421		fl := v.flag&(flagAddr|flagIndir) | v.flag.ro()
422		fl |= flag(dst.Kind())
423		return Value{dst, v.ptr, fl}
424
425	case implements(dst, v.typ()):
426		if target == nil {
427			target = unsafe_New(dst)
428		}
429		if v.Kind() == abi.Interface && v.IsNil() {
430			// A nil ReadWriter passed to nil Reader is OK,
431			// but using ifaceE2I below will panic.
432			// Avoid the panic by returning a nil dst (e.g., Reader) explicitly.
433			return Value{dst, nil, flag(abi.Interface)}
434		}
435		x := valueInterface(v)
436		if dst.NumMethod() == 0 {
437			*(*any)(target) = x
438		} else {
439			ifaceE2I(dst, x, target)
440		}
441		return Value{dst, target, flagIndir | flag(abi.Interface)}
442	}
443
444	// Failed.
445	panic(context + ": value of type " + toRType(v.typ()).String() + " is not assignable to type " + toRType(dst).String())
446}
447
448// arrayAt returns the i-th element of p,
449// an array whose elements are eltSize bytes wide.
450// The array pointed at by p must have at least i+1 elements:
451// it is invalid (but impossible to check here) to pass i >= len,
452// because then the result will point outside the array.
453// whySafe must explain why i < len. (Passing "i < len" is fine;
454// the benefit is to surface this assumption at the call site.)
455func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer {
456	return add(p, uintptr(i)*eltSize, "i < len")
457}
458
459func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer)
460
461// typedmemmove copies a value of type t to dst from src.
462//
463//go:noescape
464func typedmemmove(t *abi.Type, dst, src unsafe.Pointer)
465
466// Dummy annotation marking that the value x escapes,
467// for use in cases where the reflect code is so clever that
468// the compiler cannot follow.
469func escapes(x any) {
470	if dummy.b {
471		dummy.x = x
472	}
473}
474
475var dummy struct {
476	b bool
477	x any
478}
479