jsi 0.6.0 → 0.7.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/CHANGELOG.md +18 -0
- data/LICENSE.md +1 -1
- data/README.md +11 -6
- data/jsi.gemspec +30 -0
- data/lib/jsi/base/node.rb +183 -0
- data/lib/jsi/base.rb +135 -161
- data/lib/jsi/jsi_coder.rb +3 -3
- data/lib/jsi/metaschema.rb +0 -1
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +9 -8
- data/lib/jsi/metaschema_node.rb +48 -51
- data/lib/jsi/ptr.rb +28 -17
- data/lib/jsi/schema/application/child_application/contains.rb +11 -2
- data/lib/jsi/schema/application/child_application/items.rb +3 -3
- data/lib/jsi/schema/application/child_application/properties.rb +3 -3
- data/lib/jsi/schema/application/child_application.rb +1 -3
- data/lib/jsi/schema/application/inplace_application/dependencies.rb +1 -1
- data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +3 -3
- data/lib/jsi/schema/application/inplace_application/ref.rb +1 -1
- data/lib/jsi/schema/application/inplace_application/someof.rb +26 -11
- data/lib/jsi/schema/application/inplace_application.rb +1 -6
- data/lib/jsi/schema/ref.rb +3 -2
- data/lib/jsi/schema/schema_ancestor_node.rb +11 -17
- data/lib/jsi/schema/validation/array.rb +3 -3
- data/lib/jsi/schema/validation/const.rb +1 -1
- data/lib/jsi/schema/validation/contains.rb +1 -1
- data/lib/jsi/schema/validation/dependencies.rb +1 -1
- data/lib/jsi/schema/validation/draft04/minmax.rb +6 -6
- data/lib/jsi/schema/validation/enum.rb +1 -1
- data/lib/jsi/schema/validation/ifthenelse.rb +5 -5
- data/lib/jsi/schema/validation/items.rb +4 -4
- data/lib/jsi/schema/validation/not.rb +1 -1
- data/lib/jsi/schema/validation/numeric.rb +5 -5
- data/lib/jsi/schema/validation/object.rb +2 -2
- data/lib/jsi/schema/validation/pattern.rb +1 -1
- data/lib/jsi/schema/validation/properties.rb +3 -3
- data/lib/jsi/schema/validation/property_names.rb +1 -1
- data/lib/jsi/schema/validation/ref.rb +1 -1
- data/lib/jsi/schema/validation/required.rb +1 -1
- data/lib/jsi/schema/validation/someof.rb +3 -3
- data/lib/jsi/schema/validation/string.rb +2 -2
- data/lib/jsi/schema/validation/type.rb +1 -1
- data/lib/jsi/schema/validation.rb +1 -1
- data/lib/jsi/schema.rb +91 -85
- data/lib/jsi/schema_classes.rb +70 -45
- data/lib/jsi/schema_registry.rb +15 -5
- data/lib/jsi/schema_set.rb +42 -2
- data/lib/jsi/simple_wrap.rb +23 -4
- data/lib/jsi/util/{attr_struct.rb → private/attr_struct.rb} +40 -19
- data/lib/jsi/util/private.rb +204 -0
- data/lib/jsi/{typelike_modules.rb → util/typelike.rb} +56 -82
- data/lib/jsi/util.rb +68 -148
- data/lib/jsi/version.rb +1 -1
- data/lib/jsi.rb +1 -17
- data/lib/schemas/json-schema.org/draft-04/schema.rb +3 -1
- data/lib/schemas/json-schema.org/draft-06/schema.rb +3 -1
- data/lib/schemas/json-schema.org/draft-07/schema.rb +3 -1
- metadata +11 -9
- data/lib/jsi/pathed_node.rb +0 -116
data/lib/jsi/util.rb
CHANGED
@@ -1,11 +1,72 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module JSI
|
4
|
-
# JSI::Util
|
5
|
-
#
|
6
|
-
# @api private
|
4
|
+
# JSI::Util contains public utilities
|
7
5
|
module Util
|
8
|
-
autoload :
|
6
|
+
autoload :Private, 'jsi/util/private'
|
7
|
+
|
8
|
+
include Private
|
9
|
+
|
10
|
+
autoload :Arraylike, 'jsi/util/typelike'
|
11
|
+
autoload :Hashlike, 'jsi/util/typelike'
|
12
|
+
|
13
|
+
# yields the content of the given param `object`. for objects which have a #jsi_modified_copy
|
14
|
+
# method of their own (JSI::Base, JSI::MetaschemaNode) that method is invoked with the given
|
15
|
+
# block. otherwise the given object itself is yielded.
|
16
|
+
#
|
17
|
+
# the given block must result in a modified copy of its block parameter
|
18
|
+
# (not destructively modifying the yielded content).
|
19
|
+
#
|
20
|
+
# @yield [Object] the content of the given object. the block should result
|
21
|
+
# in a (nondestructively) modified copy of this.
|
22
|
+
# @return [object.class] modified copy of the given object
|
23
|
+
def modified_copy(object, &block)
|
24
|
+
if object.respond_to?(:jsi_modified_copy)
|
25
|
+
object.jsi_modified_copy(&block)
|
26
|
+
else
|
27
|
+
return yield(object)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# recursive method to express the given argument object in json-compatible
|
32
|
+
# types of Hash, Array, and basic types of String/boolean/numeric/nil. this
|
33
|
+
# will raise TypeError if an object is given that is not a type that seems
|
34
|
+
# to be expressable as json.
|
35
|
+
#
|
36
|
+
# similar effect could be achieved by requiring 'json/add/core' and using #as_json,
|
37
|
+
# but I don't much care for how it represents classes that are
|
38
|
+
# not naturally expressable in JSON, and prefer not to load its
|
39
|
+
# monkey-patching.
|
40
|
+
#
|
41
|
+
# @param object [Object] the object to be converted to jsonifiability
|
42
|
+
# @return [Array, Hash, String, Boolean, NilClass, Numeric] jsonifiable
|
43
|
+
# expression of param object
|
44
|
+
# @raise [TypeError] when the object (or an object nested with a hash or
|
45
|
+
# array of object) cannot be expressed as json
|
46
|
+
def as_json(object, *opt)
|
47
|
+
if object.is_a?(JSI::Base)
|
48
|
+
as_json(object.jsi_node_content, *opt)
|
49
|
+
elsif object.respond_to?(:to_hash)
|
50
|
+
(object.respond_to?(:map) ? object : object.to_hash).map do |k, v|
|
51
|
+
unless k.is_a?(Symbol) || k.respond_to?(:to_str)
|
52
|
+
raise(TypeError, "json object (hash) cannot be keyed with: #{k.pretty_inspect.chomp}")
|
53
|
+
end
|
54
|
+
{k.to_s => as_json(v, *opt)}
|
55
|
+
end.inject({}, &:update)
|
56
|
+
elsif object.respond_to?(:to_ary)
|
57
|
+
(object.respond_to?(:map) ? object : object.to_ary).map { |e| as_json(e, *opt) }
|
58
|
+
elsif [String, TrueClass, FalseClass, NilClass, Numeric].any? { |c| object.is_a?(c) }
|
59
|
+
object
|
60
|
+
elsif object.is_a?(Symbol)
|
61
|
+
object.to_s
|
62
|
+
elsif object.is_a?(Set)
|
63
|
+
as_json(object.to_a, *opt)
|
64
|
+
elsif object.respond_to?(:as_json)
|
65
|
+
as_json(object.as_json(*opt), *opt)
|
66
|
+
else
|
67
|
+
raise(TypeError, "cannot express object as json: #{object.pretty_inspect.chomp}")
|
68
|
+
end
|
69
|
+
end
|
9
70
|
|
10
71
|
# a hash copied from the given hashlike, in which any symbol keys are
|
11
72
|
# converted to strings. behavior on collisions is undefined (but in the
|
@@ -25,7 +86,7 @@ module JSI
|
|
25
86
|
unless hashlike.respond_to?(:to_hash)
|
26
87
|
raise(ArgumentError, "expected argument to be a hash; got #{hashlike.class.inspect}: #{hashlike.pretty_inspect.chomp}")
|
27
88
|
end
|
28
|
-
JSI::
|
89
|
+
JSI::Util.modified_copy(hashlike) do |hash|
|
29
90
|
out = {}
|
30
91
|
hash.each do |k, v|
|
31
92
|
out[k.is_a?(Symbol) ? k.to_s : k] = v
|
@@ -36,7 +97,7 @@ module JSI
|
|
36
97
|
|
37
98
|
def deep_stringify_symbol_keys(object)
|
38
99
|
if object.respond_to?(:to_hash)
|
39
|
-
JSI::
|
100
|
+
JSI::Util.modified_copy(object) do |hash|
|
40
101
|
out = {}
|
41
102
|
(hash.respond_to?(:each) ? hash : hash.to_hash).each do |k, v|
|
42
103
|
out[k.is_a?(Symbol) ? k.to_s : deep_stringify_symbol_keys(k)] = deep_stringify_symbol_keys(v)
|
@@ -44,7 +105,7 @@ module JSI
|
|
44
105
|
out
|
45
106
|
end
|
46
107
|
elsif object.respond_to?(:to_ary)
|
47
|
-
JSI::
|
108
|
+
JSI::Util.modified_copy(object) do |ary|
|
48
109
|
(ary.respond_to?(:each) ? ary : ary.to_ary).map do |e|
|
49
110
|
deep_stringify_symbol_keys(e)
|
50
111
|
end
|
@@ -78,147 +139,6 @@ module JSI
|
|
78
139
|
set
|
79
140
|
end
|
80
141
|
|
81
|
-
# is the given name ok to use as a ruby method name?
|
82
|
-
def ok_ruby_method_name?(name)
|
83
|
-
# must be a string
|
84
|
-
return false unless name.respond_to?(:to_str)
|
85
|
-
# must not begin with a digit
|
86
|
-
return false if name =~ /\A[0-9]/
|
87
|
-
# must not contain characters special to ruby syntax
|
88
|
-
return false if name =~ /[\\\s\#;\.,\(\)\[\]\{\}'"`%\+\-\/\*\^\|&=<>\?:!@\$~]/
|
89
|
-
|
90
|
-
return true
|
91
|
-
end
|
92
|
-
|
93
|
-
# this is the Y-combinator, which allows anonymous recursive functions. for a simple example,
|
94
|
-
# to define a recursive function to return the length of an array:
|
95
|
-
#
|
96
|
-
# length = ycomb do |len|
|
97
|
-
# proc { |list| list == [] ? 0 : 1 + len.call(list[1..-1]) }
|
98
|
-
# end
|
99
|
-
#
|
100
|
-
# length.call([0])
|
101
|
-
# # => 1
|
102
|
-
#
|
103
|
-
# see https://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator
|
104
|
-
# and chapter 9 of the little schemer, available as the sample chapter at
|
105
|
-
# https://felleisen.org/matthias/BTLS-index.html
|
106
|
-
def ycomb
|
107
|
-
proc { |f| f.call(f) }.call(proc { |f| yield proc { |*x| f.call(f).call(*x) } })
|
108
|
-
end
|
109
|
-
|
110
|
-
module FingerprintHash
|
111
|
-
# overrides BasicObject#==
|
112
|
-
def ==(other)
|
113
|
-
__id__ == other.__id__ || (other.respond_to?(:jsi_fingerprint) && other.jsi_fingerprint == self.jsi_fingerprint)
|
114
|
-
end
|
115
|
-
|
116
|
-
alias_method :eql?, :==
|
117
|
-
|
118
|
-
# overrides Kernel#hash
|
119
|
-
def hash
|
120
|
-
jsi_fingerprint.hash
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
class MemoMap
|
125
|
-
Result = Util::AttrStruct[*%w(
|
126
|
-
value
|
127
|
-
inputs
|
128
|
-
inputs_hash
|
129
|
-
)]
|
130
|
-
|
131
|
-
class Result
|
132
|
-
end
|
133
|
-
|
134
|
-
def initialize(key_by: nil, &block)
|
135
|
-
@key_by = key_by
|
136
|
-
@block = block
|
137
|
-
|
138
|
-
# each result has its own mutex to update its memoized value thread-safely
|
139
|
-
@result_mutexes = {}
|
140
|
-
# another mutex to thread-safely initialize each result mutex
|
141
|
-
@result_mutexes_mutex = Mutex.new
|
142
|
-
|
143
|
-
@results = {}
|
144
|
-
end
|
145
|
-
|
146
|
-
def [](*inputs)
|
147
|
-
if @key_by
|
148
|
-
key = @key_by.call(*inputs)
|
149
|
-
else
|
150
|
-
key = inputs
|
151
|
-
end
|
152
|
-
result_mutex = @result_mutexes_mutex.synchronize do
|
153
|
-
@result_mutexes[key] ||= Mutex.new
|
154
|
-
end
|
155
|
-
|
156
|
-
result_mutex.synchronize do
|
157
|
-
inputs_hash = inputs.hash
|
158
|
-
if @results.key?(key) && inputs_hash == @results[key].inputs_hash && inputs == @results[key].inputs
|
159
|
-
@results[key].value
|
160
|
-
else
|
161
|
-
value = @block.call(*inputs)
|
162
|
-
@results[key] = Result.new(value: value, inputs: inputs, inputs_hash: inputs_hash)
|
163
|
-
value
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
module Memoize
|
170
|
-
def self.extended(object)
|
171
|
-
object.send(:jsi_initialize_memos)
|
172
|
-
end
|
173
|
-
|
174
|
-
private
|
175
|
-
|
176
|
-
def jsi_initialize_memos
|
177
|
-
@jsi_memomaps_mutex = Mutex.new
|
178
|
-
@jsi_memomaps = {}
|
179
|
-
end
|
180
|
-
|
181
|
-
# @return [Util::MemoMap]
|
182
|
-
def jsi_memomap(name, **options, &block)
|
183
|
-
raise(Bug, 'must jsi_initialize_memos') unless @jsi_memomaps
|
184
|
-
unless @jsi_memomaps.key?(name)
|
185
|
-
@jsi_memomaps_mutex.synchronize do
|
186
|
-
# note: this ||= appears redundant with `unless @jsi_memomaps.key?(name)`,
|
187
|
-
# but that check is not thread safe. this check is.
|
188
|
-
@jsi_memomaps[name] ||= Util::MemoMap.new(**options, &block)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
@jsi_memomaps[name]
|
192
|
-
end
|
193
|
-
|
194
|
-
def jsi_memoize(name, *inputs, &block)
|
195
|
-
jsi_memomap(name, &block)[*inputs]
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
module Virtual
|
200
|
-
class InstantiationError < StandardError
|
201
|
-
end
|
202
|
-
|
203
|
-
# this virtual class is not intended to be instantiated except by its subclasses, which override #initialize
|
204
|
-
def initialize
|
205
|
-
# :nocov:
|
206
|
-
raise(InstantiationError, "cannot instantiate virtual class #{self.class}")
|
207
|
-
# :nocov:
|
208
|
-
end
|
209
|
-
|
210
|
-
# virtual_method is used to indicate that the method calling it must be implemented on the (non-virtual) subclass
|
211
|
-
def virtual_method
|
212
|
-
# :nocov:
|
213
|
-
raise(Bug, "class #{self.class} must implement #{caller_locations.first.label}")
|
214
|
-
# :nocov:
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
public
|
219
|
-
|
220
142
|
extend self
|
221
143
|
end
|
222
|
-
public
|
223
|
-
extend Util
|
224
144
|
end
|
data/lib/jsi/version.rb
CHANGED
data/lib/jsi.rb
CHANGED
@@ -9,7 +9,6 @@ require "bigdecimal"
|
|
9
9
|
require "addressable/uri"
|
10
10
|
|
11
11
|
require "jsi/util"
|
12
|
-
require "jsi/typelike_modules"
|
13
12
|
|
14
13
|
module JSI
|
15
14
|
# generally put in code paths that are not expected to be valid control flow paths.
|
@@ -30,17 +29,7 @@ module JSI
|
|
30
29
|
SCHEMAS_PATH = RESOURCES_PATH.join('schemas')
|
31
30
|
|
32
31
|
autoload :Ptr, 'jsi/ptr'
|
33
|
-
|
34
|
-
# @private
|
35
|
-
# @deprecated
|
36
|
-
module JSON
|
37
|
-
Pointer = Ptr
|
38
|
-
end
|
39
|
-
|
40
|
-
autoload :PathedNode, 'jsi/pathed_node'
|
41
|
-
autoload :Typelike, 'jsi/typelike_modules'
|
42
|
-
autoload :Hashlike, 'jsi/typelike_modules'
|
43
|
-
autoload :Arraylike, 'jsi/typelike_modules'
|
32
|
+
autoload :Typelike, 'jsi/util/typelike'
|
44
33
|
autoload :Schema, 'jsi/schema'
|
45
34
|
autoload :SchemaSet, 'jsi/schema_set'
|
46
35
|
autoload :Base, 'jsi/base'
|
@@ -77,11 +66,6 @@ module JSI
|
|
77
66
|
JSI::Schema.new_schema(schema_object, **kw).jsi_schema_module
|
78
67
|
end
|
79
68
|
|
80
|
-
# @private @deprecated
|
81
|
-
def self.class_for_schemas(schemas)
|
82
|
-
SchemaClasses.class_for_schemas(schemas.map { |schema| JSI.new_schema(schema) })
|
83
|
-
end
|
84
|
-
|
85
69
|
# `JSI.schema_registry` is the {JSI::SchemaRegistry} in which schemas are registered.
|
86
70
|
#
|
87
71
|
# @return [JSI::SchemaRegistry]
|
@@ -3,10 +3,12 @@
|
|
3
3
|
module JSI
|
4
4
|
metaschema_document = ::JSON.parse(SCHEMAS_PATH.join('json-schema.org/draft-04/schema.json').read)
|
5
5
|
JSONSchemaOrgDraft04 = MetaschemaNode.new(metaschema_document,
|
6
|
-
|
6
|
+
schema_implementation_modules: [JSI::Schema::Draft04],
|
7
7
|
).jsi_schema_module
|
8
8
|
|
9
9
|
# the JSI schema module for `http://json-schema.org/draft-04/schema`
|
10
10
|
module JSONSchemaOrgDraft04
|
11
|
+
# @!parse extend JSI::DescribesSchemaModule
|
12
|
+
# @!parse include JSI::Schema::Draft04
|
11
13
|
end
|
12
14
|
end
|
@@ -3,10 +3,12 @@
|
|
3
3
|
module JSI
|
4
4
|
metaschema_document = ::JSON.parse(SCHEMAS_PATH.join('json-schema.org/draft-06/schema.json').read)
|
5
5
|
JSONSchemaOrgDraft06 = MetaschemaNode.new(metaschema_document,
|
6
|
-
|
6
|
+
schema_implementation_modules: [JSI::Schema::Draft06],
|
7
7
|
).jsi_schema_module
|
8
8
|
|
9
9
|
# the JSI schema module for `http://json-schema.org/draft-06/schema`
|
10
10
|
module JSONSchemaOrgDraft06
|
11
|
+
# @!parse extend JSI::DescribesSchemaModule
|
12
|
+
# @!parse include JSI::Schema::Draft06
|
11
13
|
end
|
12
14
|
end
|
@@ -3,10 +3,12 @@
|
|
3
3
|
module JSI
|
4
4
|
metaschema_document = ::JSON.parse(SCHEMAS_PATH.join('json-schema.org/draft-07/schema.json').read)
|
5
5
|
JSONSchemaOrgDraft07 = MetaschemaNode.new(metaschema_document,
|
6
|
-
|
6
|
+
schema_implementation_modules: [JSI::Schema::Draft07],
|
7
7
|
).jsi_schema_module
|
8
8
|
|
9
9
|
# the JSI schema module for `http://json-schema.org/draft-07/schema`
|
10
10
|
module JSONSchemaOrgDraft07
|
11
|
+
# @!parse extend JSI::DescribesSchemaModule
|
12
|
+
# @!parse include JSI::Schema::Draft07
|
11
13
|
end
|
12
14
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ethan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -36,13 +36,14 @@ files:
|
|
36
36
|
- CHANGELOG.md
|
37
37
|
- LICENSE.md
|
38
38
|
- README.md
|
39
|
+
- jsi.gemspec
|
39
40
|
- lib/jsi.rb
|
40
41
|
- lib/jsi/base.rb
|
42
|
+
- lib/jsi/base/node.rb
|
41
43
|
- lib/jsi/jsi_coder.rb
|
42
44
|
- lib/jsi/metaschema.rb
|
43
45
|
- lib/jsi/metaschema_node.rb
|
44
46
|
- lib/jsi/metaschema_node/bootstrap_schema.rb
|
45
|
-
- lib/jsi/pathed_node.rb
|
46
47
|
- lib/jsi/ptr.rb
|
47
48
|
- lib/jsi/schema.rb
|
48
49
|
- lib/jsi/schema/application.rb
|
@@ -98,9 +99,10 @@ files:
|
|
98
99
|
- lib/jsi/schema_registry.rb
|
99
100
|
- lib/jsi/schema_set.rb
|
100
101
|
- lib/jsi/simple_wrap.rb
|
101
|
-
- lib/jsi/typelike_modules.rb
|
102
102
|
- lib/jsi/util.rb
|
103
|
-
- lib/jsi/util/
|
103
|
+
- lib/jsi/util/private.rb
|
104
|
+
- lib/jsi/util/private/attr_struct.rb
|
105
|
+
- lib/jsi/util/typelike.rb
|
104
106
|
- lib/jsi/validation.rb
|
105
107
|
- lib/jsi/validation/error.rb
|
106
108
|
- lib/jsi/validation/result.rb
|
@@ -116,7 +118,7 @@ homepage: https://github.com/notEthan/jsi
|
|
116
118
|
licenses:
|
117
119
|
- AGPL-3.0
|
118
120
|
metadata: {}
|
119
|
-
post_install_message:
|
121
|
+
post_install_message:
|
120
122
|
rdoc_options: []
|
121
123
|
require_paths:
|
122
124
|
- lib
|
@@ -131,8 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
133
|
- !ruby/object:Gem::Version
|
132
134
|
version: '0'
|
133
135
|
requirements: []
|
134
|
-
rubygems_version: 3.1.
|
135
|
-
signing_key:
|
136
|
+
rubygems_version: 3.1.6
|
137
|
+
signing_key:
|
136
138
|
specification_version: 4
|
137
139
|
summary: 'JSI: JSON Schema Instantiation'
|
138
140
|
test_files: []
|
data/lib/jsi/pathed_node.rb
DELETED
@@ -1,116 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module JSI
|
4
|
-
# this module represents a node in a document.
|
5
|
-
#
|
6
|
-
# including class MUST define
|
7
|
-
#
|
8
|
-
# - `#jsi_document` [Object] the document
|
9
|
-
# - `#jsi_ptr` [JSI::Ptr] a pointer to the node in the document
|
10
|
-
module PathedNode
|
11
|
-
# the content of this node
|
12
|
-
def jsi_node_content
|
13
|
-
content = jsi_ptr.evaluate(jsi_document)
|
14
|
-
content
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# module extending a {JSI::PathedNode} object when its jsi_node_content is Hash-like (responds to #to_hash)
|
19
|
-
module PathedHashNode
|
20
|
-
# yields each hash key and value of this node.
|
21
|
-
#
|
22
|
-
# each yielded key is the same as a key of the node content hash,
|
23
|
-
# and each yielded value is the result of self[key] (see #[]).
|
24
|
-
#
|
25
|
-
# returns an Enumerator if no block is given.
|
26
|
-
#
|
27
|
-
# @param a arguments are passed to `#[]`
|
28
|
-
# @yield [Object, Object] each key and value of this hash node
|
29
|
-
# @return [self, Enumerator] an Enumerator if invoked without a block; otherwise self
|
30
|
-
def each(*a, &block)
|
31
|
-
return to_enum(__method__) { jsi_node_content_hash_pubsend(:size) } unless block
|
32
|
-
if block.arity > 1
|
33
|
-
jsi_node_content_hash_pubsend(:each_key) { |k| yield k, self[k, *a] }
|
34
|
-
else
|
35
|
-
jsi_node_content_hash_pubsend(:each_key) { |k| yield [k, self[k, *a]] }
|
36
|
-
end
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
# a hash in which each key is a key of the jsi_node_content hash and each value is the
|
41
|
-
# result of `self[key]`
|
42
|
-
# @param a arguments are passed to `#[]`
|
43
|
-
# @return [Hash]
|
44
|
-
def to_hash(*a)
|
45
|
-
{}.tap { |h| jsi_node_content_hash_pubsend(:each_key) { |k| h[k] = self[k, *a] } }
|
46
|
-
end
|
47
|
-
|
48
|
-
include Hashlike
|
49
|
-
|
50
|
-
# invokes the method with the given name on the jsi_node_content (if defined) or its #to_hash
|
51
|
-
# @param method_name [String, Symbol]
|
52
|
-
# @param a arguments and block are passed to the invocation of method_name
|
53
|
-
# @return [Object] the result of calling method method_name on the jsi_node_content or its #to_hash
|
54
|
-
def jsi_node_content_hash_pubsend(method_name, *a, &b)
|
55
|
-
if jsi_node_content.respond_to?(method_name)
|
56
|
-
jsi_node_content.public_send(method_name, *a, &b)
|
57
|
-
else
|
58
|
-
jsi_node_content.to_hash.public_send(method_name, *a, &b)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# methods that don't look at the value; can skip the overhead of #[] (invoked by #to_hash)
|
63
|
-
SAFE_KEY_ONLY_METHODS.each do |method_name|
|
64
|
-
define_method(method_name) do |*a, &b|
|
65
|
-
jsi_node_content_hash_pubsend(method_name, *a, &b)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
module PathedArrayNode
|
71
|
-
# yields each array element of this node.
|
72
|
-
#
|
73
|
-
# each yielded element is the result of self[index] for each index of our array (see #[]).
|
74
|
-
#
|
75
|
-
# returns an Enumerator if no block is given.
|
76
|
-
#
|
77
|
-
# @param a arguments are passed to `#[]`
|
78
|
-
# @yield [Object] each element of this array node
|
79
|
-
# @return [self, Enumerator] an Enumerator if invoked without a block; otherwise self
|
80
|
-
def each(*a, &block)
|
81
|
-
return to_enum(__method__) { jsi_node_content_ary_pubsend(:size) } unless block
|
82
|
-
jsi_node_content_ary_pubsend(:each_index) { |i| yield(self[i, *a]) }
|
83
|
-
self
|
84
|
-
end
|
85
|
-
|
86
|
-
# an array, the same size as the jsi_node_content, in which the element at each index is the
|
87
|
-
# result of `self[index]`
|
88
|
-
# @param a arguments are passed to `#[]`
|
89
|
-
# @return [Array]
|
90
|
-
def to_ary(*a)
|
91
|
-
to_a(*a)
|
92
|
-
end
|
93
|
-
|
94
|
-
include Arraylike
|
95
|
-
|
96
|
-
# invokes the method with the given name on the jsi_node_content (if defined) or its #to_ary
|
97
|
-
# @param method_name [String, Symbol]
|
98
|
-
# @param a arguments and block are passed to the invocation of method_name
|
99
|
-
# @return [Object] the result of calling method method_name on the jsi_node_content or its #to_ary
|
100
|
-
def jsi_node_content_ary_pubsend(method_name, *a, &b)
|
101
|
-
if jsi_node_content.respond_to?(method_name)
|
102
|
-
jsi_node_content.public_send(method_name, *a, &b)
|
103
|
-
else
|
104
|
-
jsi_node_content.to_ary.public_send(method_name, *a, &b)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# methods that don't look at the value; can skip the overhead of #[] (invoked by #to_a).
|
109
|
-
# we override these methods from Arraylike
|
110
|
-
SAFE_INDEX_ONLY_METHODS.each do |method_name|
|
111
|
-
define_method(method_name) do |*a, &b|
|
112
|
-
jsi_node_content_ary_pubsend(method_name, *a, &b)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|