1// Copyright 2024 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 reflect
6
7import "iter"
8
9func rangeNum[T int8 | int16 | int32 | int64 | int |
10	uint8 | uint16 | uint32 | uint64 | uint |
11	uintptr, N int64 | uint64](v N) iter.Seq[Value] {
12	return func(yield func(v Value) bool) {
13		// cannot use range T(v) because no core type.
14		for i := T(0); i < T(v); i++ {
15			if !yield(ValueOf(i)) {
16				return
17			}
18		}
19	}
20}
21
22// Seq returns an iter.Seq[Value] that loops over the elements of v.
23// If v's kind is Func, it must be a function that has no results and
24// that takes a single argument of type func(T) bool for some type T.
25// If v's kind is Pointer, the pointer element type must have kind Array.
26// Otherwise v's kind must be Int, Int8, Int16, Int32, Int64,
27// Uint, Uint8, Uint16, Uint32, Uint64, Uintptr,
28// Array, Chan, Map, Slice, or String.
29func (v Value) Seq() iter.Seq[Value] {
30	if canRangeFunc(v.typ()) {
31		return func(yield func(Value) bool) {
32			rf := MakeFunc(v.Type().In(0), func(in []Value) []Value {
33				return []Value{ValueOf(yield(in[0]))}
34			})
35			v.Call([]Value{rf})
36		}
37	}
38	switch v.Kind() {
39	case Int:
40		return rangeNum[int](v.Int())
41	case Int8:
42		return rangeNum[int8](v.Int())
43	case Int16:
44		return rangeNum[int16](v.Int())
45	case Int32:
46		return rangeNum[int32](v.Int())
47	case Int64:
48		return rangeNum[int64](v.Int())
49	case Uint:
50		return rangeNum[uint](v.Uint())
51	case Uint8:
52		return rangeNum[uint8](v.Uint())
53	case Uint16:
54		return rangeNum[uint16](v.Uint())
55	case Uint32:
56		return rangeNum[uint32](v.Uint())
57	case Uint64:
58		return rangeNum[uint64](v.Uint())
59	case Uintptr:
60		return rangeNum[uintptr](v.Uint())
61	case Pointer:
62		if v.Elem().kind() != Array {
63			break
64		}
65		return func(yield func(Value) bool) {
66			v = v.Elem()
67			for i := range v.Len() {
68				if !yield(ValueOf(i)) {
69					return
70				}
71			}
72		}
73	case Array, Slice:
74		return func(yield func(Value) bool) {
75			for i := range v.Len() {
76				if !yield(ValueOf(i)) {
77					return
78				}
79			}
80		}
81	case String:
82		return func(yield func(Value) bool) {
83			for i := range v.String() {
84				if !yield(ValueOf(i)) {
85					return
86				}
87			}
88		}
89	case Map:
90		return func(yield func(Value) bool) {
91			i := v.MapRange()
92			for i.Next() {
93				if !yield(i.Key()) {
94					return
95				}
96			}
97		}
98	case Chan:
99		return func(yield func(Value) bool) {
100			for value, ok := v.Recv(); ok; value, ok = v.Recv() {
101				if !yield(value) {
102					return
103				}
104			}
105		}
106	}
107	panic("reflect: " + v.Type().String() + " cannot produce iter.Seq[Value]")
108}
109
110// Seq2 returns an iter.Seq2[Value, Value] that loops over the elements of v.
111// If v's kind is Func, it must be a function that has no results and
112// that takes a single argument of type func(K, V) bool for some type K, V.
113// If v's kind is Pointer, the pointer element type must have kind Array.
114// Otherwise v's kind must be Array, Map, Slice, or String.
115func (v Value) Seq2() iter.Seq2[Value, Value] {
116	if canRangeFunc2(v.typ()) {
117		return func(yield func(Value, Value) bool) {
118			rf := MakeFunc(v.Type().In(0), func(in []Value) []Value {
119				return []Value{ValueOf(yield(in[0], in[1]))}
120			})
121			v.Call([]Value{rf})
122		}
123	}
124	switch v.Kind() {
125	case Pointer:
126		if v.Elem().kind() != Array {
127			break
128		}
129		return func(yield func(Value, Value) bool) {
130			v = v.Elem()
131			for i := range v.Len() {
132				if !yield(ValueOf(i), v.Index(i)) {
133					return
134				}
135			}
136		}
137	case Array, Slice:
138		return func(yield func(Value, Value) bool) {
139			for i := range v.Len() {
140				if !yield(ValueOf(i), v.Index(i)) {
141					return
142				}
143			}
144		}
145	case String:
146		return func(yield func(Value, Value) bool) {
147			for i, v := range v.String() {
148				if !yield(ValueOf(i), ValueOf(v)) {
149					return
150				}
151			}
152		}
153	case Map:
154		return func(yield func(Value, Value) bool) {
155			i := v.MapRange()
156			for i.Next() {
157				if !yield(i.Key(), i.Value()) {
158					return
159				}
160			}
161		}
162	}
163	panic("reflect: " + v.Type().String() + " cannot produce iter.Seq2[Value, Value]")
164}
165