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
|
# File 'lib/odin/transform/verbs/object_verbs.rb', line 23
def register(registry)
dv = Types::DynValue
registry["keys"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
return dv.of_null if obj.nil?
dv.of_array(obj.keys.map { |k| dv.of_string(k) })
}
registry["values"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
return dv.of_null if obj.nil?
dv.of_array(obj.values)
}
registry["entries"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
return dv.of_null if obj.nil?
result = obj.map { |k, v| dv.of_array([dv.of_string(k), v]) }
dv.of_array(result)
}
registry["has"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
key = args[1]&.to_string || ""
dv.of_bool(obj&.key?(key) || false)
}
registry["get"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
key = args[1]&.to_string || ""
default_val = args[2] || dv.of_null
if obj && obj.key?(key)
obj[key]
else
default_val
end
}
registry["merge"] = ->(args, _ctx) {
result = {}
args.each do |a|
obj = ObjectVerbs.(a)
result.merge!(obj) if obj
end
result.empty? ? dv.of_null : dv.of_object(result)
}
registry["jsonPath"] = ->(args, _ctx) {
root = args[0]
path = args[1]&.to_string || ""
return dv.of_null if root.nil? || root.null? || path.empty?
parts = path.sub(/^\$\.?/, "").split(".")
current = root
parts.each do |part|
break if current.nil? || current.null?
if part =~ /^(.+)\[(\d+)\]$/
field = $1
idx = $2.to_i
current = current.object? ? current.get(field) : nil
current = current&.array? ? (current.value[idx] || dv.of_null) : dv.of_null
elsif current.object?
current = current.get(part)
elsif current.array?
idx = part.to_i
current = current.value[idx] || dv.of_null
else
current = nil
end
end
current || dv.of_null
}
registry["extract"] = ->(args, _ctx) {
return dv.of_null if args.length < 2
s = args[0]&.to_string || ""
pattern = args[1]&.to_string || ""
group = args.length >= 3 ? (args[2]&.to_number || 0).floor : 0
begin
match = Regexp.new(pattern).match(s)
rescue RegexpError
return dv.of_null
end
return dv.of_null if match.nil?
return dv.of_null if group.negative? || group >= match.size
captured = match[group]
captured.nil? ? dv.of_null : dv.of_string(captured)
}
end
|