1package param
2
3import (
4 "fmt"
5 "reflect"
6)
7
8var paramUnionType = reflect.TypeOf(APIUnion{})
9
10// VariantFromUnion can be used to extract the present variant from a param union type.
11// A param union type is a struct with an embedded field of [APIUnion].
12func VariantFromUnion(u reflect.Value) (any, error) {
13 if u.Kind() == reflect.Ptr {
14 u = u.Elem()
15 }
16
17 if u.Kind() != reflect.Struct {
18 return nil, fmt.Errorf("param: cannot extract variant from non-struct union")
19 }
20
21 isUnion := false
22 nVariants := 0
23 variantIdx := -1
24 for i := 0; i < u.NumField(); i++ {
25 if !u.Field(i).IsZero() {
26 nVariants++
27 variantIdx = i
28 }
29 if u.Field(i).Type() == paramUnionType {
30 isUnion = u.Type().Field(i).Anonymous
31 }
32 }
33
34 if !isUnion {
35 return nil, fmt.Errorf("param: cannot extract variant from non-union")
36 }
37
38 if nVariants > 1 {
39 return nil, fmt.Errorf("param: cannot extract variant from union with multiple variants")
40 }
41
42 if nVariants == 0 {
43 return nil, fmt.Errorf("param: cannot extract variant from union with no variants")
44 }
45
46 return u.Field(variantIdx).Interface(), nil
47}