This repository has been archived by the owner on Jun 7, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
pick.go
132 lines (114 loc) · 2.76 KB
/
pick.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package structural
import (
"fmt"
"reflect"
"cuelang.org/go/cue"
)
func CuePick(sorig, spick string) (string, error) {
out := NewpvStruct()
vorigi, err := r.Compile("", sorig)
if err != nil {
return "", err
}
vorig := vorigi.Value()
if vorig.Err() != nil {
return "", vorig.Err()
}
vpicki, err := r.Compile("", spick)
if err != nil {
return "", err
}
vpick := vpicki.Value()
if vpick.Err() != nil {
return "", vpick.Err()
}
err = cuePick(out, vorig, vpick)
if err != nil {
return "", err
}
return out.ToString()
}
func cuePick(out *pvStruct, vorig, vpick cue.Value) error {
// Loop over the keys in pick
vpickStruct, err := vpick.Struct()
if err != nil {
return err
}
vpickIter := vpickStruct.Fields()
for vpickIter.Next() {
key := vpickIter.Label()
pickVal := vpickIter.Value()
origLookup, err := vorig.LookupField(key)
// Ignore anythig not in orig
if err != nil {
continue
}
origVal := origLookup.Value
// If orig is a builtin and unifies with pick, then use it
if isBuiltin(origVal) && origVal.Unify(pickVal).Kind() != cue.BottomKind {
out.Set(key, *ExprFromValue(origVal))
continue
}
if isList(origVal) {
lval := NewpvList()
origListIter, err := origVal.List()
if err != nil {
return err
}
// If orig is a list but pick isn't, keep all elements
// of the list that unify with pick
if !isList(pickVal) {
for origListIter.Next() {
elem := origListIter.Value()
if elem.Unify(pickVal).Kind() != cue.BottomKind {
lval.Append(*ExprFromValue(elem))
}
}
} else if isList(pickVal) {
// Else, consider element-wise
pickListIter, err := pickVal.List()
if err != nil {
return err
}
for origListIter.Next() && pickListIter.Next() {
origElem := origListIter.Value()
pickElem := pickListIter.Value()
if origElem.Unify(pickElem).Kind() != cue.BottomKind {
lval.Append(*ExprFromValue(origElem))
}
}
}
out.Set(key, *lval.ToExpr())
}
// If orig is a struct then recurse
if isStruct(origVal) {
rval := NewpvStruct()
err = cuePick(rval, origVal, pickVal)
if err != nil {
return err
}
out.Set(key, *rval.ToExpr())
}
}
return nil
}
///////////
func Pick(orig, pick interface{}) (interface{}, error) {
O, ook := orig.(cue.Value)
P, pok := pick.(cue.Value)
if ook && pok {
return PickCue(O, P)
}
if !(ook || pok) {
return PickGo(orig, pick)
}
return nil, fmt.Errorf("structural.Pick - Incompatible types %v and %v", reflect.TypeOf(orig), reflect.TypeOf(pick))
}
func PickCue(orig, pick cue.Value) (cue.Value, error) {
fmt.Println("PickCue - no implemented")
return cue.Value{}, nil
}
func PickGo(orig, pick interface{}) (interface{}, error) {
fmt.Println("PickGo - no implemented")
return nil, nil
}