babl-json 0.3.4 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/babl/nodes.rb +1 -0
- data/lib/babl/nodes/concat.rb +115 -0
- data/lib/babl/nodes/fixed_array.rb +2 -0
- data/lib/babl/nodes/merge.rb +9 -4
- data/lib/babl/operators.rb +1 -0
- data/lib/babl/operators/concat.rb +27 -0
- data/lib/babl/schema/any_of.rb +28 -1
- data/lib/babl/schema/fixed_array.rb +5 -1
- data/lib/babl/template.rb +1 -0
- data/lib/babl/utils.rb +1 -0
- data/lib/babl/utils/array.rb +8 -0
- data/lib/babl/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03dff31c23ccad4de2970e0e9f1e8c0ac2df3257
|
4
|
+
data.tar.gz: 88bfe61b0d2fcfc20ff71a4e009d6ddf15416e00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9c04e5150dd7aeda65aefcb989f4a72eb5aed5b5afd0f18edae0495818e45b6fad658c1d693375ff711329c0c036e0c333d0d5ce99349f100c8a2da0b98f07c
|
7
|
+
data.tar.gz: 720f05f879639374ab4a26bc7be49b4d32c6fb7c8534621643d09bb2d3a4f402cedc8af994682268760fcdc2418ac72e6cf7e9ffd9bda8dbf14d4d914683cec7
|
data/lib/babl/nodes.rb
CHANGED
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'babl/errors'
|
3
|
+
require 'babl/utils'
|
4
|
+
require 'babl/schema'
|
5
|
+
|
6
|
+
module Babl
|
7
|
+
module Nodes
|
8
|
+
class Concat < Utils::Value.new(:nodes)
|
9
|
+
def dependencies
|
10
|
+
nodes.map(&:dependencies).reduce(Utils::Hash::EMPTY) { |a, b| Babl::Utils::Hash.deep_merge(a, b) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def pinned_dependencies
|
14
|
+
nodes.map(&:pinned_dependencies).reduce(Utils::Hash::EMPTY) { |a, b| Babl::Utils::Hash.deep_merge(a, b) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def schema
|
18
|
+
nodes.map(&:schema).reduce(Schema::FixedArray::EMPTY) { |a, b| merge_doc(a, b) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def render(ctx)
|
22
|
+
out = []
|
23
|
+
nodes.each { |node|
|
24
|
+
values = node.render(ctx)
|
25
|
+
case values
|
26
|
+
when ::NilClass then nil
|
27
|
+
when ::Array then out.concat(values)
|
28
|
+
else raise Errors::RenderingError, "Only arrays can be concatenated\n" + ctx.formatted_stack
|
29
|
+
end
|
30
|
+
}
|
31
|
+
out
|
32
|
+
end
|
33
|
+
|
34
|
+
def optimize
|
35
|
+
optimize_empty ||
|
36
|
+
optimize_single ||
|
37
|
+
optimize_concatenated_arrays ||
|
38
|
+
optimize_preconcat_constant ||
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def optimize_empty
|
45
|
+
Constant.new(Utils::Array::EMPTY, Schema::FixedArray::EMPTY) if nodes.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def optimize_single
|
49
|
+
return unless nodes.size == 1
|
50
|
+
optimized = nodes.first.optimize
|
51
|
+
case
|
52
|
+
when FixedArray === optimized
|
53
|
+
optimized
|
54
|
+
when Constant === optimized
|
55
|
+
optimized.value.nil? ? FixedArray::EMPTY : optimized
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def optimize_concatenated_arrays
|
60
|
+
optimized_nodes = nodes.map(&:optimize)
|
61
|
+
return if optimized_nodes == nodes
|
62
|
+
Concat.new(optimized_nodes).optimize
|
63
|
+
end
|
64
|
+
|
65
|
+
def optimize_preconcat_constant
|
66
|
+
nodes.each_cons(2).each_with_index do |(obj1, obj2), idx|
|
67
|
+
obj1 = constant_to_array(obj1) if Constant === obj1
|
68
|
+
obj2 = constant_to_array(obj2) if Constant === obj2
|
69
|
+
next unless FixedArray === obj1 && FixedArray === obj2
|
70
|
+
new_nodes = nodes.dup
|
71
|
+
new_nodes[idx] = FixedArray.new(obj1.nodes + obj2.nodes)
|
72
|
+
new_nodes[idx + 1] = nil
|
73
|
+
return Concat.new(new_nodes.compact).optimize
|
74
|
+
end
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
|
78
|
+
def constant_to_array(constant)
|
79
|
+
case constant.schema
|
80
|
+
when Schema::FixedArray
|
81
|
+
FixedArray.new(constant.schema.items.each_with_index.map { |item, index|
|
82
|
+
Constant.new(constant.value[index], item)
|
83
|
+
})
|
84
|
+
when Schema::Primitive::NULL
|
85
|
+
FixedArray::EMPTY
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Merging documentations from concatenated hashes is lossy, because neither JSON-Schema
|
90
|
+
# or our internal representation of arrays is able to model that.
|
91
|
+
def merge_doc(doc1, doc2)
|
92
|
+
doc1 = Schema::FixedArray::EMPTY if doc1 == Schema::Primitive::NULL
|
93
|
+
doc2 = Schema::FixedArray::EMPTY if doc2 == Schema::Primitive::NULL
|
94
|
+
|
95
|
+
case
|
96
|
+
when Schema::Anything === doc1 || Schema::Anything === doc2
|
97
|
+
Schema::DynArray.new(Schema::Anything.instance)
|
98
|
+
when Schema::FixedArray === doc1 && Schema::FixedArray === doc2
|
99
|
+
Schema::FixedArray.new(doc1.items + doc2.items)
|
100
|
+
when Schema::AnyOf === doc2
|
101
|
+
Schema::AnyOf.canonicalized(doc2.choice_set.map { |c| merge_doc(doc1, c) })
|
102
|
+
when Schema::AnyOf === doc1
|
103
|
+
Schema::AnyOf.canonicalized(doc1.choice_set.map { |c| merge_doc(c, doc2) })
|
104
|
+
when Schema::DynArray === doc1 && Schema::FixedArray === doc2
|
105
|
+
Schema::DynArray.new(Schema::AnyOf.canonicalized([doc1.item] + doc2.items))
|
106
|
+
when Schema::FixedArray === doc1 && Schema::DynArray === doc2
|
107
|
+
Schema::DynArray.new(Schema::AnyOf.canonicalized(doc1.items + [doc2.item]))
|
108
|
+
when Schema::DynArray === doc1 && Schema::DynArray === doc2
|
109
|
+
Schema::DynArray.new(Schema::AnyOf.canonicalized([doc1.item, doc2.item]))
|
110
|
+
else raise Errors::InvalidTemplate, 'Only arrays can be concatenated'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/babl/nodes/merge.rb
CHANGED
@@ -29,8 +29,8 @@ module Babl
|
|
29
29
|
def optimize
|
30
30
|
optimize_empty ||
|
31
31
|
optimize_single ||
|
32
|
-
optimize_merged_objects ||
|
33
32
|
optimize_nested_merges ||
|
33
|
+
optimize_merged_objects ||
|
34
34
|
optimize_premergeable_objects ||
|
35
35
|
self
|
36
36
|
end
|
@@ -45,14 +45,17 @@ module Babl
|
|
45
45
|
return unless nodes.size == 1
|
46
46
|
optimized = nodes.first.optimize
|
47
47
|
case
|
48
|
-
when Object === optimized
|
49
|
-
|
48
|
+
when Object === optimized
|
49
|
+
optimized
|
50
|
+
when Constant === optimized
|
51
|
+
optimized.value.nil? ? Object::EMPTY : optimized
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
55
|
def optimize_merged_objects
|
54
56
|
optimized_nodes = nodes.map(&:optimize)
|
55
|
-
optimized_nodes == nodes
|
57
|
+
return if optimized_nodes == nodes
|
58
|
+
Merge.new(optimized_nodes).optimize
|
56
59
|
end
|
57
60
|
|
58
61
|
def optimize_nested_merges
|
@@ -80,6 +83,8 @@ module Babl
|
|
80
83
|
Object.new(constant.schema.property_set.map { |property|
|
81
84
|
[property.name, Constant.new(constant.value[property.name], property.value)]
|
82
85
|
}.to_h)
|
86
|
+
when Schema::Primitive::NULL
|
87
|
+
Object::EMPTY
|
83
88
|
end
|
84
89
|
end
|
85
90
|
|
data/lib/babl/operators.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'babl/nodes'
|
3
|
+
|
4
|
+
module Babl
|
5
|
+
module Operators
|
6
|
+
module Concat
|
7
|
+
module DSL
|
8
|
+
# Produce an array by concatening the provided result of the given templates.
|
9
|
+
# (they therefor have to produce arrays, or nil, which is interpreted as an empty array)
|
10
|
+
def concat(*templates)
|
11
|
+
templates = templates.map { |t| unscoped.call(t) }
|
12
|
+
|
13
|
+
construct_terminal { |context|
|
14
|
+
Nodes::Concat.new(
|
15
|
+
templates.map { |t|
|
16
|
+
t.builder.precompile(
|
17
|
+
Nodes::TerminalValue.instance,
|
18
|
+
context.merge(continue: nil)
|
19
|
+
)
|
20
|
+
}
|
21
|
+
)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/babl/schema/any_of.rb
CHANGED
@@ -26,6 +26,8 @@ module Babl
|
|
26
26
|
simplify_push_down_dyn_array ||
|
27
27
|
simplify_dyn_and_fixed_array ||
|
28
28
|
simplify_merge_objects ||
|
29
|
+
simplify_integer_is_number ||
|
30
|
+
simplify_many_fixed_arrays ||
|
29
31
|
self
|
30
32
|
end
|
31
33
|
|
@@ -35,6 +37,31 @@ module Babl
|
|
35
37
|
|
36
38
|
private
|
37
39
|
|
40
|
+
def simplify_integer_is_number
|
41
|
+
return unless choice_set.include?(Typed::INTEGER) && choice_set.include?(Typed::NUMBER)
|
42
|
+
AnyOf.canonicalized(choice_set - [Typed::INTEGER])
|
43
|
+
end
|
44
|
+
|
45
|
+
# AnyOf[FixedArray(Item1, Item2), FixedArray(Item3, Item4)] can be summarized
|
46
|
+
# by DynArray(AnyOf(Item1, Item2, Item3, Item4)). It is a lossy transformation
|
47
|
+
# but it will help reducing the number of permutations when the operator concat() is used.
|
48
|
+
def simplify_many_fixed_arrays
|
49
|
+
choice_set.each_with_index { |obj1, index1|
|
50
|
+
next unless FixedArray === obj1
|
51
|
+
|
52
|
+
choice_set.each_with_index { |obj2, index2|
|
53
|
+
break if index2 >= index1
|
54
|
+
next unless FixedArray === obj2
|
55
|
+
|
56
|
+
return AnyOf.canonicalized(choice_set - [obj1, obj2] + [
|
57
|
+
DynArray.new(AnyOf.new(obj1.items + obj2.items))
|
58
|
+
])
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
|
38
65
|
# We can completely get rid of the AnyOf element of there is only one possible schema.
|
39
66
|
def simplify_single
|
40
67
|
choice_set.size == 1 ? choice_set.first : nil
|
@@ -96,7 +123,7 @@ module Babl
|
|
96
123
|
nil
|
97
124
|
end
|
98
125
|
|
99
|
-
# Merge all objects together. This is
|
126
|
+
# Merge all objects together. This is a lossy simplification, but it will greatly reduce the size
|
100
127
|
# of the generated schema. On top of that, when the JSON-Schema is translated into Typescript, it produces
|
101
128
|
# a much more workable type definition (union of anonymous object types is not practical to use)
|
102
129
|
def simplify_merge_objects
|
data/lib/babl/template.rb
CHANGED
data/lib/babl/utils.rb
CHANGED
data/lib/babl/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: babl-json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Frederic Terrazzoni
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-10-
|
11
|
+
date: 2017-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -135,6 +135,7 @@ files:
|
|
135
135
|
- lib/babl/builder/template_base.rb
|
136
136
|
- lib/babl/errors.rb
|
137
137
|
- lib/babl/nodes.rb
|
138
|
+
- lib/babl/nodes/concat.rb
|
138
139
|
- lib/babl/nodes/constant.rb
|
139
140
|
- lib/babl/nodes/create_pin.rb
|
140
141
|
- lib/babl/nodes/dep.rb
|
@@ -154,6 +155,7 @@ files:
|
|
154
155
|
- lib/babl/operators.rb
|
155
156
|
- lib/babl/operators/array.rb
|
156
157
|
- lib/babl/operators/call.rb
|
158
|
+
- lib/babl/operators/concat.rb
|
157
159
|
- lib/babl/operators/continue.rb
|
158
160
|
- lib/babl/operators/default.rb
|
159
161
|
- lib/babl/operators/dep.rb
|
@@ -189,6 +191,7 @@ files:
|
|
189
191
|
- lib/babl/schema/typed.rb
|
190
192
|
- lib/babl/template.rb
|
191
193
|
- lib/babl/utils.rb
|
194
|
+
- lib/babl/utils/array.rb
|
192
195
|
- lib/babl/utils/dsl_proxy.rb
|
193
196
|
- lib/babl/utils/hash.rb
|
194
197
|
- lib/babl/utils/ref.rb
|