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