babl-json 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|