1// Copyright (c) 2021, Peter Ohler, All rights reserved.
2
3package alt
4
5import (
6	"reflect"
7	"unsafe"
8)
9
10const (
11	strMask   = byte(0x01)
12	omitMask  = byte(0x02)
13	embedMask = byte(0x04)
14)
15
16var nilValue reflect.Value
17
18type valFunc func(fi *finfo, rv reflect.Value, addr uintptr) (v interface{}, fv reflect.Value, omit bool)
19
20type finfo struct {
21	rt     reflect.Type
22	key    string
23	value  valFunc
24	ivalue valFunc
25	index  []int
26	offset uintptr
27}
28
29func valString(fi *finfo, rv reflect.Value, addr uintptr) (interface{}, reflect.Value, bool) {
30	return rv.FieldByIndex(fi.index).String(), nilValue, false
31}
32
33func valStringNotEmpty(fi *finfo, rv reflect.Value, addr uintptr) (interface{}, reflect.Value, bool) {
34	s := rv.FieldByIndex(fi.index).String()
35	if len(s) == 0 {
36		return s, nilValue, true
37	}
38	return s, nilValue, false
39}
40
41func valJustVal(fi *finfo, rv reflect.Value, addr uintptr) (interface{}, reflect.Value, bool) {
42	fv := rv.FieldByIndex(fi.index)
43	return fv.Interface(), fv, false
44}
45
46func valPtrNotEmpty(fi *finfo, rv reflect.Value, addr uintptr) (interface{}, reflect.Value, bool) {
47	fv := rv.FieldByIndex(fi.index)
48	v := fv.Interface()
49	return v, fv, (*[2]uintptr)(unsafe.Pointer(&v))[1] == 0
50}
51
52func valSliceNotEmpty(fi *finfo, rv reflect.Value, addr uintptr) (interface{}, reflect.Value, bool) {
53	fv := rv.FieldByIndex(fi.index)
54	if fv.Len() == 0 {
55		return nil, nilValue, true
56	}
57	return fv.Interface(), fv, false
58}
59
60func valSimplifier(fi *finfo, rv reflect.Value, addr uintptr) (interface{}, reflect.Value, bool) {
61	v := rv.FieldByIndex(fi.index).Interface()
62	if (*[2]uintptr)(unsafe.Pointer(&v))[1] == 0 {
63		return nil, nilValue, false
64	}
65	return v.(Simplifier).Simplify(), nilValue, false
66}
67
68func valSimplifierAddr(fi *finfo, rv reflect.Value, addr uintptr) (interface{}, reflect.Value, bool) {
69	v := rv.FieldByIndex(fi.index).Addr().Interface()
70	return v.(Simplifier).Simplify(), nilValue, false
71}
72
73func valGenericer(fi *finfo, rv reflect.Value, addr uintptr) (interface{}, reflect.Value, bool) {
74	v := rv.FieldByIndex(fi.index).Interface()
75	if (*[2]uintptr)(unsafe.Pointer(&v))[1] == 0 {
76		return nil, nilValue, false
77	}
78	if g, _ := v.(Genericer); g != nil {
79		if n := g.Generic(); n != nil {
80			return n.Simplify(), nilValue, false
81		}
82	}
83	return nil, nilValue, false
84}
85
86func valGenericerAddr(fi *finfo, rv reflect.Value, addr uintptr) (interface{}, reflect.Value, bool) {
87	v := rv.FieldByIndex(fi.index).Addr().Interface()
88	if g, _ := v.(Genericer); g != nil {
89		if n := g.Generic(); n != nil {
90			return n.Simplify(), nilValue, false
91		}
92	}
93	return nil, nilValue, false
94}
95
96func newFinfo(f reflect.StructField, key string, fx byte) *finfo {
97	fi := finfo{
98		rt:     f.Type,
99		key:    key,
100		index:  f.Index,
101		value:  valJustVal, // replace as necessary later
102		ivalue: valJustVal, // replace as necessary later
103		offset: f.Offset,
104	}
105	// Check for interfaces first since almost any type can implement one of
106	// the supported interfaces.
107	vp := reflect.New(fi.rt).Interface()
108	v := reflect.New(fi.rt).Elem().Interface()
109	if _, ok := v.(Simplifier); ok {
110		fi.value = valSimplifier
111		fi.ivalue = valSimplifier
112		return &fi
113	}
114	if _, ok := vp.(Simplifier); ok {
115		fi.value = valSimplifierAddr
116		fi.ivalue = valSimplifierAddr
117		return &fi
118	}
119	if _, ok := v.(Genericer); ok {
120		fi.value = valGenericer
121		fi.ivalue = valGenericer
122		return &fi
123	}
124	if _, ok := vp.(Genericer); ok {
125		fi.value = valGenericerAddr
126		fi.ivalue = valGenericerAddr
127		return &fi
128	}
129	switch f.Type.Kind() {
130	case reflect.Bool:
131		fi.value = boolValFuncs[fx]
132		fi.ivalue = boolValFuncs[fx|embedMask]
133
134	case reflect.Int:
135		fi.value = intValFuncs[fx]
136		fi.ivalue = intValFuncs[fx|embedMask]
137	case reflect.Int8:
138		fi.value = int8ValFuncs[fx]
139		fi.ivalue = int8ValFuncs[fx|embedMask]
140	case reflect.Int16:
141		fi.value = int16ValFuncs[fx]
142		fi.ivalue = int16ValFuncs[fx|embedMask]
143	case reflect.Int32:
144		fi.value = int32ValFuncs[fx]
145		fi.ivalue = int32ValFuncs[fx|embedMask]
146	case reflect.Int64:
147		fi.value = int64ValFuncs[fx]
148		fi.ivalue = int64ValFuncs[fx|embedMask]
149
150	case reflect.Uint:
151		fi.value = uintValFuncs[fx]
152		fi.ivalue = uintValFuncs[fx|embedMask]
153	case reflect.Uint8:
154		fi.value = uint8ValFuncs[fx]
155		fi.ivalue = uint8ValFuncs[fx|embedMask]
156	case reflect.Uint16:
157		fi.value = uint16ValFuncs[fx]
158		fi.ivalue = uint16ValFuncs[fx|embedMask]
159	case reflect.Uint32:
160		fi.value = uint32ValFuncs[fx]
161		fi.ivalue = uint32ValFuncs[fx|embedMask]
162	case reflect.Uint64:
163		fi.value = uint64ValFuncs[fx]
164		fi.ivalue = uint64ValFuncs[fx|embedMask]
165
166	case reflect.Float32:
167		fi.value = float32ValFuncs[fx]
168		fi.ivalue = float32ValFuncs[fx|embedMask]
169	case reflect.Float64:
170		fi.value = float64ValFuncs[fx]
171		fi.ivalue = float64ValFuncs[fx|embedMask]
172
173	case reflect.String:
174		if (fx & omitMask) != 0 {
175			fi.value = valStringNotEmpty
176			fi.ivalue = valStringNotEmpty
177		} else {
178			fi.value = valString
179			fi.ivalue = valString
180		}
181	case reflect.Struct:
182		fi.value = valJustVal
183		fi.ivalue = valJustVal
184	case reflect.Ptr:
185		if (fx & omitMask) != 0 {
186			fi.value = valPtrNotEmpty
187			fi.ivalue = valPtrNotEmpty
188		} else {
189			fi.value = valJustVal
190			fi.ivalue = valJustVal
191		}
192	case reflect.Interface:
193		if (fx & omitMask) != 0 {
194			fi.value = valPtrNotEmpty
195			fi.ivalue = valPtrNotEmpty
196		} else {
197			fi.value = valJustVal
198			fi.ivalue = valJustVal
199		}
200	case reflect.Slice, reflect.Array, reflect.Map:
201		if (fx & omitMask) != 0 {
202			fi.value = valSliceNotEmpty
203			fi.ivalue = valSliceNotEmpty
204		} else {
205			fi.value = valJustVal
206			fi.ivalue = valJustVal
207		}
208	}
209	return &fi
210}
211