jsi 0.6.0 → 0.8.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/.yardopts +6 -1
 - data/CHANGELOG.md +33 -0
 - data/LICENSE.md +1 -1
 - data/README.md +29 -23
 - data/jsi.gemspec +29 -0
 - data/lib/jsi/base/mutability.rb +44 -0
 - data/lib/jsi/base/node.rb +348 -0
 - data/lib/jsi/base.rb +497 -339
 - data/lib/jsi/jsi_coder.rb +19 -17
 - data/lib/jsi/metaschema_node/bootstrap_schema.rb +61 -26
 - data/lib/jsi/metaschema_node.rb +161 -133
 - data/lib/jsi/ptr.rb +80 -47
 - data/lib/jsi/schema/application/child_application/contains.rb +11 -2
 - data/lib/jsi/schema/application/child_application/draft04.rb +0 -1
 - data/lib/jsi/schema/application/child_application/draft06.rb +0 -1
 - data/lib/jsi/schema/application/child_application/draft07.rb +0 -1
 - 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 +0 -27
 - data/lib/jsi/schema/application/inplace_application/dependencies.rb +1 -1
 - data/lib/jsi/schema/application/inplace_application/draft04.rb +0 -1
 - data/lib/jsi/schema/application/inplace_application/draft06.rb +0 -1
 - data/lib/jsi/schema/application/inplace_application/draft07.rb +0 -1
 - data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +3 -3
 - data/lib/jsi/schema/application/inplace_application/ref.rb +2 -2
 - data/lib/jsi/schema/application/inplace_application/someof.rb +26 -11
 - data/lib/jsi/schema/application/inplace_application.rb +0 -32
 - data/lib/jsi/schema/draft04.rb +0 -1
 - data/lib/jsi/schema/draft06.rb +0 -1
 - data/lib/jsi/schema/draft07.rb +0 -1
 - data/lib/jsi/schema/ref.rb +46 -19
 - data/lib/jsi/schema/schema_ancestor_node.rb +69 -66
 - 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 +2 -2
 - data/lib/jsi/schema/validation/dependencies.rb +1 -1
 - data/lib/jsi/schema/validation/draft04/minmax.rb +8 -6
 - data/lib/jsi/schema/validation/draft04.rb +0 -2
 - data/lib/jsi/schema/validation/draft06.rb +0 -2
 - data/lib/jsi/schema/validation/draft07.rb +0 -2
 - 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 +7 -7
 - 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 +2 -2
 - data/lib/jsi/schema/validation/properties.rb +7 -7
 - data/lib/jsi/schema/validation/property_names.rb +1 -1
 - data/lib/jsi/schema/validation/ref.rb +2 -2
 - 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 -3
 - data/lib/jsi/schema.rb +443 -226
 - data/lib/jsi/schema_classes.rb +241 -147
 - data/lib/jsi/schema_registry.rb +78 -19
 - data/lib/jsi/schema_set.rb +114 -28
 - data/lib/jsi/simple_wrap.rb +18 -4
 - data/lib/jsi/util/private/attr_struct.rb +141 -0
 - data/lib/jsi/util/private/memo_map.rb +75 -0
 - data/lib/jsi/util/private.rb +185 -0
 - data/lib/jsi/{typelike_modules.rb → util/typelike.rb} +79 -105
 - data/lib/jsi/util.rb +157 -153
 - data/lib/jsi/validation/error.rb +4 -0
 - data/lib/jsi/validation/result.rb +18 -32
 - data/lib/jsi/version.rb +1 -1
 - data/lib/jsi.rb +65 -39
 - data/lib/schemas/json-schema.org/draft-04/schema.rb +160 -3
 - data/lib/schemas/json-schema.org/draft-06/schema.rb +162 -3
 - data/lib/schemas/json-schema.org/draft-07/schema.rb +189 -3
 - metadata +27 -11
 - data/lib/jsi/metaschema.rb +0 -7
 - data/lib/jsi/pathed_node.rb +0 -116
 - data/lib/jsi/schema/validation/core.rb +0 -39
 - data/lib/jsi/util/attr_struct.rb +0 -106
 
    
        data/lib/jsi/ptr.rb
    CHANGED
    
    | 
         @@ -16,12 +16,17 @@ module JSI 
     | 
|
| 
       16 
16 
     | 
    
         
             
                  class ResolutionError < Error
         
     | 
| 
       17 
17 
     | 
    
         
             
                  end
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
      
 19 
     | 
    
         
            +
                  POS_INT_RE = /\A[1-9]\d*\z/
         
     | 
| 
      
 20 
     | 
    
         
            +
                  private_constant :POS_INT_RE
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
       19 
22 
     | 
    
         
             
                  # instantiates a pointer or returns the given pointer
         
     | 
| 
       20 
23 
     | 
    
         
             
                  # @param ary_ptr [#to_ary, JSI::Ptr] an array of tokens, or a pointer
         
     | 
| 
       21 
24 
     | 
    
         
             
                  # @return [JSI::Ptr]
         
     | 
| 
       22 
25 
     | 
    
         
             
                  def self.ary_ptr(ary_ptr)
         
     | 
| 
       23 
26 
     | 
    
         
             
                    if ary_ptr.is_a?(Ptr)
         
     | 
| 
       24 
27 
     | 
    
         
             
                      ary_ptr
         
     | 
| 
      
 28 
     | 
    
         
            +
                    elsif ary_ptr == Util::EMPTY_ARY
         
     | 
| 
      
 29 
     | 
    
         
            +
                      EMPTY
         
     | 
| 
       25 
30 
     | 
    
         
             
                    else
         
     | 
| 
       26 
31 
     | 
    
         
             
                      new(ary_ptr)
         
     | 
| 
       27 
32 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -31,7 +36,7 @@ module JSI 
     | 
|
| 
       31 
36 
     | 
    
         
             
                  #
         
     | 
| 
       32 
37 
     | 
    
         
             
                  #     JSI::Ptr[]
         
     | 
| 
       33 
38 
     | 
    
         
             
                  #
         
     | 
| 
       34 
     | 
    
         
            -
                  #  
     | 
| 
      
 39 
     | 
    
         
            +
                  # instantiates a root pointer.
         
     | 
| 
       35 
40 
     | 
    
         
             
                  #
         
     | 
| 
       36 
41 
     | 
    
         
             
                  #     JSI::Ptr['a', 'b']
         
     | 
| 
       37 
42 
     | 
    
         
             
                  #     JSI::Ptr['a']['b']
         
     | 
| 
         @@ -42,7 +47,7 @@ module JSI 
     | 
|
| 
       42 
47 
     | 
    
         
             
                  # @param tokens any number of tokens
         
     | 
| 
       43 
48 
     | 
    
         
             
                  # @return [JSI::Ptr]
         
     | 
| 
       44 
49 
     | 
    
         
             
                  def self.[](*tokens)
         
     | 
| 
       45 
     | 
    
         
            -
                    new(tokens)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    tokens.empty? ? EMPTY : new(tokens.freeze)
         
     | 
| 
       46 
51 
     | 
    
         
             
                  end
         
     | 
| 
       47 
52 
     | 
    
         | 
| 
       48 
53 
     | 
    
         
             
                  # parse a URI-escaped fragment and instantiate as a JSI::Ptr
         
     | 
| 
         @@ -55,6 +60,12 @@ module JSI 
     | 
|
| 
       55 
60 
     | 
    
         
             
                  #     JSI::Ptr.from_fragment('/foo%20bar')
         
     | 
| 
       56 
61 
     | 
    
         
             
                  #     => JSI::Ptr["foo bar"]
         
     | 
| 
       57 
62 
     | 
    
         
             
                  #
         
     | 
| 
      
 63 
     | 
    
         
            +
                  # Note: A fragment does not include a leading '#'. The string "#/foo" is a URI containing the
         
     | 
| 
      
 64 
     | 
    
         
            +
                  # fragment "/foo", which should be parsed by `Addressable::URI` before passing to this method, e.g.:
         
     | 
| 
      
 65 
     | 
    
         
            +
                  #
         
     | 
| 
      
 66 
     | 
    
         
            +
                  #     JSI::Ptr.from_fragment(Addressable::URI.parse("#/foo").fragment)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  #     => JSI::Ptr["foo"]
         
     | 
| 
      
 68 
     | 
    
         
            +
                  #
         
     | 
| 
       58 
69 
     | 
    
         
             
                  # @param fragment [String] a fragment containing a pointer
         
     | 
| 
       59 
70 
     | 
    
         
             
                  # @return [JSI::Ptr]
         
     | 
| 
       60 
71 
     | 
    
         
             
                  # @raise [JSI::Ptr::PointerSyntaxError] when the fragment does not contain a pointer with
         
     | 
| 
         @@ -75,13 +86,17 @@ module JSI 
     | 
|
| 
       75 
86 
     | 
    
         
             
                  # @return [JSI::Ptr]
         
     | 
| 
       76 
87 
     | 
    
         
             
                  # @raise [JSI::Ptr::PointerSyntaxError] when the pointer_string does not have valid pointer syntax
         
     | 
| 
       77 
88 
     | 
    
         
             
                  def self.from_pointer(pointer_string)
         
     | 
| 
       78 
     | 
    
         
            -
                     
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
                       
     | 
| 
      
 89 
     | 
    
         
            +
                    pointer_string = pointer_string.to_str
         
     | 
| 
      
 90 
     | 
    
         
            +
                    if pointer_string[0] == ?/
         
     | 
| 
      
 91 
     | 
    
         
            +
                      tokens = pointer_string.split('/', -1).map! do |piece|
         
     | 
| 
      
 92 
     | 
    
         
            +
                        piece.gsub!('~1', '/')
         
     | 
| 
      
 93 
     | 
    
         
            +
                        piece.gsub!('~0', '~')
         
     | 
| 
      
 94 
     | 
    
         
            +
                        piece.freeze
         
     | 
| 
      
 95 
     | 
    
         
            +
                      end
         
     | 
| 
      
 96 
     | 
    
         
            +
                      tokens.shift
         
     | 
| 
      
 97 
     | 
    
         
            +
                      new(tokens.freeze)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    elsif pointer_string.empty?
         
     | 
| 
      
 99 
     | 
    
         
            +
                      EMPTY
         
     | 
| 
       85 
100 
     | 
    
         
             
                    else
         
     | 
| 
       86 
101 
     | 
    
         
             
                      raise(PointerSyntaxError, "Invalid pointer syntax in #{pointer_string.inspect}: pointer must begin with /")
         
     | 
| 
       87 
102 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -94,14 +109,11 @@ module JSI 
     | 
|
| 
       94 
109 
     | 
    
         
             
                    unless tokens.respond_to?(:to_ary)
         
     | 
| 
       95 
110 
     | 
    
         
             
                      raise(TypeError, "tokens must be an array. got: #{tokens.inspect}")
         
     | 
| 
       96 
111 
     | 
    
         
             
                    end
         
     | 
| 
       97 
     | 
    
         
            -
                    @tokens = tokens.to_ary 
     | 
| 
      
 112 
     | 
    
         
            +
                    @tokens = Util.deep_to_frozen(tokens.to_ary, not_implemented: proc { |o| o })
         
     | 
| 
       98 
113 
     | 
    
         
             
                  end
         
     | 
| 
       99 
114 
     | 
    
         | 
| 
       100 
115 
     | 
    
         
             
                  attr_reader :tokens
         
     | 
| 
       101 
116 
     | 
    
         | 
| 
       102 
     | 
    
         
            -
                  # @private @deprecated
         
     | 
| 
       103 
     | 
    
         
            -
                  alias_method :reference_tokens, :tokens
         
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
117 
     | 
    
         
             
                  # takes a root json document and evaluates this pointer through the document, returning the value
         
     | 
| 
       106 
118 
     | 
    
         
             
                  # pointed to by this pointer.
         
     | 
| 
       107 
119 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -109,9 +121,9 @@ module JSI 
     | 
|
| 
       109 
121 
     | 
    
         
             
                  # @param a arguments are passed to each invocation of `#[]`
         
     | 
| 
       110 
122 
     | 
    
         
             
                  # @return [Object] the content of the document pointed to by this pointer
         
     | 
| 
       111 
123 
     | 
    
         
             
                  # @raise [JSI::Ptr::ResolutionError] the document does not contain the path this pointer references
         
     | 
| 
       112 
     | 
    
         
            -
                  def evaluate(document, *a)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  def evaluate(document, *a, **kw)
         
     | 
| 
       113 
125 
     | 
    
         
             
                    res = tokens.inject(document) do |value, token|
         
     | 
| 
       114 
     | 
    
         
            -
                      _, child = node_subscript_token_child(value, token, *a)
         
     | 
| 
      
 126 
     | 
    
         
            +
                      _, child = node_subscript_token_child(value, token, *a, **kw)
         
     | 
| 
       115 
127 
     | 
    
         
             
                      child
         
     | 
| 
       116 
128 
     | 
    
         
             
                    end
         
     | 
| 
       117 
129 
     | 
    
         
             
                    res
         
     | 
| 
         @@ -120,19 +132,19 @@ module JSI 
     | 
|
| 
       120 
132 
     | 
    
         
             
                  # the pointer string representation of this pointer
         
     | 
| 
       121 
133 
     | 
    
         
             
                  # @return [String]
         
     | 
| 
       122 
134 
     | 
    
         
             
                  def pointer
         
     | 
| 
       123 
     | 
    
         
            -
                    tokens.map { |t| '/' + t.to_s.gsub('~', '~0').gsub('/', '~1') }.join('')
         
     | 
| 
      
 135 
     | 
    
         
            +
                    tokens.map { |t| '/' + t.to_s.gsub('~', '~0').gsub('/', '~1') }.join('').freeze
         
     | 
| 
       124 
136 
     | 
    
         
             
                  end
         
     | 
| 
       125 
137 
     | 
    
         | 
| 
       126 
138 
     | 
    
         
             
                  # the fragment string representation of this pointer
         
     | 
| 
       127 
139 
     | 
    
         
             
                  # @return [String]
         
     | 
| 
       128 
140 
     | 
    
         
             
                  def fragment
         
     | 
| 
       129 
     | 
    
         
            -
                    Addressable::URI.escape(pointer)
         
     | 
| 
      
 141 
     | 
    
         
            +
                    Addressable::URI.escape(pointer).freeze
         
     | 
| 
       130 
142 
     | 
    
         
             
                  end
         
     | 
| 
       131 
143 
     | 
    
         | 
| 
       132 
144 
     | 
    
         
             
                  # a URI consisting of a fragment containing this pointer's fragment string representation
         
     | 
| 
       133 
145 
     | 
    
         
             
                  # @return [Addressable::URI]
         
     | 
| 
       134 
146 
     | 
    
         
             
                  def uri
         
     | 
| 
       135 
     | 
    
         
            -
                    Addressable::URI.new(fragment: fragment)
         
     | 
| 
      
 147 
     | 
    
         
            +
                    Addressable::URI.new(fragment: fragment).freeze
         
     | 
| 
       136 
148 
     | 
    
         
             
                  end
         
     | 
| 
       137 
149 
     | 
    
         | 
| 
       138 
150 
     | 
    
         
             
                  # whether this pointer is empty, i.e. it has no tokens
         
     | 
| 
         @@ -151,26 +163,32 @@ module JSI 
     | 
|
| 
       151 
163 
     | 
    
         
             
                  def parent
         
     | 
| 
       152 
164 
     | 
    
         
             
                    if root?
         
     | 
| 
       153 
165 
     | 
    
         
             
                      raise(Ptr::Error, "cannot access parent of root pointer: #{pretty_inspect.chomp}")
         
     | 
| 
       154 
     | 
    
         
            -
                    else
         
     | 
| 
       155 
     | 
    
         
            -
                      Ptr.new(tokens[0...-1])
         
     | 
| 
       156 
166 
     | 
    
         
             
                    end
         
     | 
| 
      
 167 
     | 
    
         
            +
                    tokens.size == 1 ? EMPTY : Ptr.new(tokens[0...-1].freeze)
         
     | 
| 
       157 
168 
     | 
    
         
             
                  end
         
     | 
| 
       158 
169 
     | 
    
         | 
| 
       159 
     | 
    
         
            -
                  # whether this pointer  
     | 
| 
       160 
     | 
    
         
            -
                  #  
     | 
| 
      
 170 
     | 
    
         
            +
                  # whether this pointer is an ancestor of `other_ptr`, a descendent pointer.
         
     | 
| 
      
 171 
     | 
    
         
            +
                  # `ancestor_of?` is inclusive; a pointer is an ancestor of itself.
         
     | 
| 
      
 172 
     | 
    
         
            +
                  #
         
     | 
| 
       161 
173 
     | 
    
         
             
                  # @return [Boolean]
         
     | 
| 
      
 174 
     | 
    
         
            +
                  def ancestor_of?(other_ptr)
         
     | 
| 
      
 175 
     | 
    
         
            +
                    tokens == other_ptr.tokens[0...tokens.size]
         
     | 
| 
      
 176 
     | 
    
         
            +
                  end
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                  # @deprecated
         
     | 
| 
       162 
179 
     | 
    
         
             
                  def contains?(other_ptr)
         
     | 
| 
       163 
     | 
    
         
            -
                     
     | 
| 
      
 180 
     | 
    
         
            +
                    ancestor_of?(other_ptr)
         
     | 
| 
       164 
181 
     | 
    
         
             
                  end
         
     | 
| 
       165 
182 
     | 
    
         | 
| 
       166 
183 
     | 
    
         
             
                  # part of this pointer relative to the given ancestor_ptr
         
     | 
| 
       167 
184 
     | 
    
         
             
                  # @return [JSI::Ptr]
         
     | 
| 
       168 
185 
     | 
    
         
             
                  # @raise [JSI::Ptr::Error] if the given ancestor_ptr is not an ancestor of this pointer
         
     | 
| 
       169 
     | 
    
         
            -
                  def  
     | 
| 
       170 
     | 
    
         
            -
                     
     | 
| 
      
 186 
     | 
    
         
            +
                  def relative_to(ancestor_ptr)
         
     | 
| 
      
 187 
     | 
    
         
            +
                    return self if ancestor_ptr.empty?
         
     | 
| 
      
 188 
     | 
    
         
            +
                    unless ancestor_ptr.ancestor_of?(self)
         
     | 
| 
       171 
189 
     | 
    
         
             
                      raise(Error, "ancestor_ptr #{ancestor_ptr.inspect} is not ancestor of #{inspect}")
         
     | 
| 
       172 
190 
     | 
    
         
             
                    end
         
     | 
| 
       173 
     | 
    
         
            -
                    Ptr.new(tokens[ancestor_ptr.tokens.size..-1])
         
     | 
| 
      
 191 
     | 
    
         
            +
                    ancestor_ptr.tokens.size == tokens.size ? EMPTY : Ptr.new(tokens[ancestor_ptr.tokens.size..-1].freeze)
         
     | 
| 
       174 
192 
     | 
    
         
             
                  end
         
     | 
| 
       175 
193 
     | 
    
         | 
| 
       176 
194 
     | 
    
         
             
                  # a pointer with the tokens of this one plus the given `ptr`'s.
         
     | 
| 
         @@ -182,9 +200,9 @@ module JSI 
     | 
|
| 
       182 
200 
     | 
    
         
             
                    elsif ptr.respond_to?(:to_ary)
         
     | 
| 
       183 
201 
     | 
    
         
             
                      ptr_tokens = ptr
         
     | 
| 
       184 
202 
     | 
    
         
             
                    else
         
     | 
| 
       185 
     | 
    
         
            -
                      raise(TypeError, "ptr must be a  
     | 
| 
      
 203 
     | 
    
         
            +
                      raise(TypeError, "ptr must be a #{Ptr} or Array of tokens; got: #{ptr.inspect}")
         
     | 
| 
       186 
204 
     | 
    
         
             
                    end
         
     | 
| 
       187 
     | 
    
         
            -
                    Ptr.new( 
     | 
| 
      
 205 
     | 
    
         
            +
                    ptr_tokens.empty? ? self : Ptr.new((tokens + ptr_tokens).freeze)
         
     | 
| 
       188 
206 
     | 
    
         
             
                  end
         
     | 
| 
       189 
207 
     | 
    
         | 
| 
       190 
208 
     | 
    
         
             
                  # a pointer consisting of the first `n` of our tokens
         
     | 
| 
         @@ -192,10 +210,10 @@ module JSI 
     | 
|
| 
       192 
210 
     | 
    
         
             
                  # @return [JSI::Ptr]
         
     | 
| 
       193 
211 
     | 
    
         
             
                  # @raise [ArgumentError] if n is not between 0 and the size of our tokens
         
     | 
| 
       194 
212 
     | 
    
         
             
                  def take(n)
         
     | 
| 
       195 
     | 
    
         
            -
                    unless (0 
     | 
| 
      
 213 
     | 
    
         
            +
                    unless n.is_a?(Integer) && n >= 0 && n <= tokens.size
         
     | 
| 
       196 
214 
     | 
    
         
             
                      raise(ArgumentError, "n not in range (0..#{tokens.size}): #{n.inspect}")
         
     | 
| 
       197 
215 
     | 
    
         
             
                    end
         
     | 
| 
       198 
     | 
    
         
            -
                    Ptr.new(tokens.take(n))
         
     | 
| 
      
 216 
     | 
    
         
            +
                    n == tokens.size ? self : Ptr.new(tokens.take(n).freeze)
         
     | 
| 
       199 
217 
     | 
    
         
             
                  end
         
     | 
| 
       200 
218 
     | 
    
         | 
| 
       201 
219 
     | 
    
         
             
                  # appends the given token to this pointer's tokens and returns the result
         
     | 
| 
         @@ -203,7 +221,7 @@ module JSI 
     | 
|
| 
       203 
221 
     | 
    
         
             
                  # @param token [Object]
         
     | 
| 
       204 
222 
     | 
    
         
             
                  # @return [JSI::Ptr] pointer to a child node of this pointer with the given token
         
     | 
| 
       205 
223 
     | 
    
         
             
                  def [](token)
         
     | 
| 
       206 
     | 
    
         
            -
                    Ptr.new(tokens 
     | 
| 
      
 224 
     | 
    
         
            +
                    Ptr.new(tokens.dup.push(token).freeze)
         
     | 
| 
       207 
225 
     | 
    
         
             
                  end
         
     | 
| 
       208 
226 
     | 
    
         | 
| 
       209 
227 
     | 
    
         
             
                  # takes a document and a block. the block is yielded the content of the given document at this
         
     | 
| 
         @@ -225,10 +243,10 @@ module JSI 
     | 
|
| 
       225 
243 
     | 
    
         
             
                    # or hash in the path above the node we point to. this node's content is modified by the
         
     | 
| 
       226 
244 
     | 
    
         
             
                    # caller, and that is recursively merged up to the document root.
         
     | 
| 
       227 
245 
     | 
    
         
             
                    if empty?
         
     | 
| 
       228 
     | 
    
         
            -
                       
     | 
| 
      
 246 
     | 
    
         
            +
                      Util.modified_copy(document, &block)
         
     | 
| 
       229 
247 
     | 
    
         
             
                    else
         
     | 
| 
       230 
248 
     | 
    
         
             
                      car = tokens[0]
         
     | 
| 
       231 
     | 
    
         
            -
                      cdr = Ptr.new(tokens[1..-1])
         
     | 
| 
      
 249 
     | 
    
         
            +
                      cdr = tokens.size == 1 ? EMPTY : Ptr.new(tokens[1..-1].freeze)
         
     | 
| 
       232 
250 
     | 
    
         
             
                      token, document_child = node_subscript_token_child(document, car)
         
     | 
| 
       233 
251 
     | 
    
         
             
                      modified_document_child = cdr.modified_document_copy(document_child, &block)
         
     | 
| 
       234 
252 
     | 
    
         
             
                      if modified_document_child.object_id == document_child.object_id
         
     | 
| 
         @@ -247,42 +265,57 @@ module JSI 
     | 
|
| 
       247 
265 
     | 
    
         
             
                  # a string representation of this pointer
         
     | 
| 
       248 
266 
     | 
    
         
             
                  # @return [String]
         
     | 
| 
       249 
267 
     | 
    
         
             
                  def inspect
         
     | 
| 
       250 
     | 
    
         
            -
                    "#{self.class.name}[#{tokens.map(&:inspect).join(", ")}]"
         
     | 
| 
      
 268 
     | 
    
         
            +
                    -"#{self.class.name}[#{tokens.map(&:inspect).join(", ")}]"
         
     | 
| 
       251 
269 
     | 
    
         
             
                  end
         
     | 
| 
       252 
270 
     | 
    
         | 
| 
       253 
     | 
    
         
            -
                   
     | 
| 
      
 271 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 272 
     | 
    
         
            +
                    inspect
         
     | 
| 
      
 273 
     | 
    
         
            +
                  end
         
     | 
| 
       254 
274 
     | 
    
         | 
| 
       255 
     | 
    
         
            -
                  #  
     | 
| 
      
 275 
     | 
    
         
            +
                  # see {Util::Private::FingerprintHash}
         
     | 
| 
      
 276 
     | 
    
         
            +
                  # @api private
         
     | 
| 
       256 
277 
     | 
    
         
             
                  def jsi_fingerprint
         
     | 
| 
       257 
     | 
    
         
            -
                    {class: Ptr, tokens: tokens}
         
     | 
| 
      
 278 
     | 
    
         
            +
                    {class: Ptr, tokens: tokens}.freeze
         
     | 
| 
       258 
279 
     | 
    
         
             
                  end
         
     | 
| 
       259 
     | 
    
         
            -
                  include Util::FingerprintHash
         
     | 
| 
      
 280 
     | 
    
         
            +
                  include Util::FingerprintHash::Immutable
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
                  EMPTY = new(Util::EMPTY_ARY)
         
     | 
| 
       260 
283 
     | 
    
         | 
| 
       261 
284 
     | 
    
         
             
                  private
         
     | 
| 
       262 
285 
     | 
    
         | 
| 
       263 
     | 
    
         
            -
                  def node_subscript_token_child(value, token, *a)
         
     | 
| 
      
 286 
     | 
    
         
            +
                  def node_subscript_token_child(value, token, *a, **kw)
         
     | 
| 
       264 
287 
     | 
    
         
             
                    if value.respond_to?(:to_ary)
         
     | 
| 
       265 
     | 
    
         
            -
                      if token.is_a?(String) && token =~  
     | 
| 
      
 288 
     | 
    
         
            +
                      if token.is_a?(String) && (token == '0' || token =~ POS_INT_RE)
         
     | 
| 
       266 
289 
     | 
    
         
             
                        token = token.to_i
         
     | 
| 
       267 
290 
     | 
    
         
             
                      elsif token == '-'
         
     | 
| 
       268 
291 
     | 
    
         
             
                        # per rfc6901, - refers "to the (nonexistent) member after the last array element" and is
         
     | 
| 
       269 
292 
     | 
    
         
             
                        # expected to raise an error condition.
         
     | 
| 
       270 
293 
     | 
    
         
             
                        raise(ResolutionError, "Invalid resolution: #{token.inspect} refers to a nonexistent element in array #{value.inspect}")
         
     | 
| 
       271 
294 
     | 
    
         
             
                      end
         
     | 
| 
       272 
     | 
    
         
            -
                       
     | 
| 
       273 
     | 
    
         
            -
             
     | 
| 
       274 
     | 
    
         
            -
             
     | 
| 
       275 
     | 
    
         
            -
                      unless (0...(value.respond_to?(:size) ? value : value.to_ary).size).include?(token)
         
     | 
| 
       276 
     | 
    
         
            -
                        raise(ResolutionError, "Invalid resolution: #{token.inspect} is not a valid index of #{value.inspect}")
         
     | 
| 
      
 295 
     | 
    
         
            +
                      size = (value.respond_to?(:size) ? value : value.to_ary).size
         
     | 
| 
      
 296 
     | 
    
         
            +
                      unless token.is_a?(Integer) && token >= 0 && token < size
         
     | 
| 
      
 297 
     | 
    
         
            +
                        raise(ResolutionError, "Invalid resolution: #{token.inspect} is not a valid array index of #{value.inspect}")
         
     | 
| 
       277 
298 
     | 
    
         
             
                      end
         
     | 
| 
       278 
299 
     | 
    
         | 
| 
       279 
     | 
    
         
            -
                       
     | 
| 
      
 300 
     | 
    
         
            +
                      ary = (value.respond_to?(:[]) ? value : value.to_ary)
         
     | 
| 
      
 301 
     | 
    
         
            +
                      if kw.empty?
         
     | 
| 
      
 302 
     | 
    
         
            +
                        # TODO remove eventually (keyword argument compatibility)
         
     | 
| 
      
 303 
     | 
    
         
            +
                        child = ary[token, *a]
         
     | 
| 
      
 304 
     | 
    
         
            +
                      else
         
     | 
| 
      
 305 
     | 
    
         
            +
                        child = ary[token, *a, **kw]
         
     | 
| 
      
 306 
     | 
    
         
            +
                      end
         
     | 
| 
       280 
307 
     | 
    
         
             
                    elsif value.respond_to?(:to_hash)
         
     | 
| 
       281 
308 
     | 
    
         
             
                      unless (value.respond_to?(:key?) ? value : value.to_hash).key?(token)
         
     | 
| 
       282 
309 
     | 
    
         
             
                        raise(ResolutionError, "Invalid resolution: #{token.inspect} is not a valid key of #{value.inspect}")
         
     | 
| 
       283 
310 
     | 
    
         
             
                      end
         
     | 
| 
       284 
311 
     | 
    
         | 
| 
       285 
     | 
    
         
            -
                       
     | 
| 
      
 312 
     | 
    
         
            +
                      hsh = (value.respond_to?(:[]) ? value : value.to_hash)
         
     | 
| 
      
 313 
     | 
    
         
            +
                      if kw.empty?
         
     | 
| 
      
 314 
     | 
    
         
            +
                        # TODO remove eventually (keyword argument compatibility)
         
     | 
| 
      
 315 
     | 
    
         
            +
                        child = hsh[token, *a]
         
     | 
| 
      
 316 
     | 
    
         
            +
                      else
         
     | 
| 
      
 317 
     | 
    
         
            +
                        child = hsh[token, *a, **kw]
         
     | 
| 
      
 318 
     | 
    
         
            +
                      end
         
     | 
| 
       286 
319 
     | 
    
         
             
                    else
         
     | 
| 
       287 
320 
     | 
    
         
             
                      raise(ResolutionError, "Invalid resolution: #{token.inspect} cannot be resolved in #{value.inspect}")
         
     | 
| 
       288 
321 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -4,11 +4,20 @@ module JSI 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::ChildApplication::Contains
         
     | 
| 
       5 
5 
     | 
    
         
             
                # @private
         
     | 
| 
       6 
6 
     | 
    
         
             
                def internal_applicate_contains(idx, instance, &block)
         
     | 
| 
       7 
     | 
    
         
            -
                  if  
     | 
| 
      
 7 
     | 
    
         
            +
                  if keyword?('contains')
         
     | 
| 
       8 
8 
     | 
    
         
             
                    contains_schema = subschema(['contains'])
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
                     
     | 
| 
      
 10 
     | 
    
         
            +
                    child_idx_valid = Hash.new { |h, i| h[i] = contains_schema.instance_valid?(instance[i]) }
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    if child_idx_valid[idx]
         
     | 
| 
       11 
13 
     | 
    
         
             
                      yield contains_schema
         
     | 
| 
      
 14 
     | 
    
         
            +
                    else
         
     | 
| 
      
 15 
     | 
    
         
            +
                      instance_valid = instance.each_index.any? { |i| child_idx_valid[i] }
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                      unless instance_valid
         
     | 
| 
      
 18 
     | 
    
         
            +
                        # invalid application: if contains_schema does not validate against any child, it applies to every child
         
     | 
| 
      
 19 
     | 
    
         
            +
                        yield contains_schema
         
     | 
| 
      
 20 
     | 
    
         
            +
                      end
         
     | 
| 
       12 
21 
     | 
    
         
             
                    end
         
     | 
| 
       13 
22 
     | 
    
         
             
                  end
         
     | 
| 
       14 
23 
     | 
    
         
             
                end
         
     | 
| 
         @@ -2,7 +2,6 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module JSI
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::ChildApplication::Draft06
         
     | 
| 
       5 
     | 
    
         
            -
                include Schema::Application::ChildApplication
         
     | 
| 
       6 
5 
     | 
    
         
             
                include Schema::Application::ChildApplication::Items
         
     | 
| 
       7 
6 
     | 
    
         
             
                include Schema::Application::ChildApplication::Contains
         
     | 
| 
       8 
7 
     | 
    
         
             
                include Schema::Application::ChildApplication::Properties
         
     | 
| 
         @@ -2,7 +2,6 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module JSI
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::ChildApplication::Draft07
         
     | 
| 
       5 
     | 
    
         
            -
                include Schema::Application::ChildApplication
         
     | 
| 
       6 
5 
     | 
    
         
             
                include Schema::Application::ChildApplication::Items
         
     | 
| 
       7 
6 
     | 
    
         
             
                include Schema::Application::ChildApplication::Contains
         
     | 
| 
       8 
7 
     | 
    
         
             
                include Schema::Application::ChildApplication::Properties
         
     | 
| 
         @@ -4,13 +4,13 @@ module JSI 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::ChildApplication::Items
         
     | 
| 
       5 
5 
     | 
    
         
             
                # @private
         
     | 
| 
       6 
6 
     | 
    
         
             
                def internal_applicate_items(idx, &block)
         
     | 
| 
       7 
     | 
    
         
            -
                  if schema_content['items'].respond_to?(:to_ary)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  if keyword?('items') && schema_content['items'].respond_to?(:to_ary)
         
     | 
| 
       8 
8 
     | 
    
         
             
                    if schema_content['items'].each_index.to_a.include?(idx)
         
     | 
| 
       9 
9 
     | 
    
         
             
                      yield subschema(['items', idx])
         
     | 
| 
       10 
     | 
    
         
            -
                    elsif  
     | 
| 
      
 10 
     | 
    
         
            +
                    elsif keyword?('additionalItems')
         
     | 
| 
       11 
11 
     | 
    
         
             
                      yield subschema(['additionalItems'])
         
     | 
| 
       12 
12 
     | 
    
         
             
                    end
         
     | 
| 
       13 
     | 
    
         
            -
                  elsif  
     | 
| 
      
 13 
     | 
    
         
            +
                  elsif keyword?('items')
         
     | 
| 
       14 
14 
     | 
    
         
             
                    yield subschema(['items'])
         
     | 
| 
       15 
15 
     | 
    
         
             
                  end
         
     | 
| 
       16 
16 
     | 
    
         
             
                end
         
     | 
| 
         @@ -5,11 +5,11 @@ module JSI 
     | 
|
| 
       5 
5 
     | 
    
         
             
                # @private
         
     | 
| 
       6 
6 
     | 
    
         
             
                def internal_applicate_properties(property_name, &block)
         
     | 
| 
       7 
7 
     | 
    
         
             
                  apply_additional = true
         
     | 
| 
       8 
     | 
    
         
            -
                  if  
     | 
| 
      
 8 
     | 
    
         
            +
                  if keyword?('properties') && schema_content['properties'].respond_to?(:to_hash) && schema_content['properties'].key?(property_name)
         
     | 
| 
       9 
9 
     | 
    
         
             
                    apply_additional = false
         
     | 
| 
       10 
10 
     | 
    
         
             
                    yield subschema(['properties', property_name])
         
     | 
| 
       11 
11 
     | 
    
         
             
                  end
         
     | 
| 
       12 
     | 
    
         
            -
                  if schema_content['patternProperties'].respond_to?(:to_hash)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  if keyword?('patternProperties') && schema_content['patternProperties'].respond_to?(:to_hash)
         
     | 
| 
       13 
13 
     | 
    
         
             
                    schema_content['patternProperties'].each_key do |pattern|
         
     | 
| 
       14 
14 
     | 
    
         
             
                      if pattern.respond_to?(:to_str) && property_name.to_s =~ Regexp.new(pattern) # TODO map pattern to ruby syntax
         
     | 
| 
       15 
15 
     | 
    
         
             
                        apply_additional = false
         
     | 
| 
         @@ -17,7 +17,7 @@ module JSI 
     | 
|
| 
       17 
17 
     | 
    
         
             
                      end
         
     | 
| 
       18 
18 
     | 
    
         
             
                    end
         
     | 
| 
       19 
19 
     | 
    
         
             
                  end
         
     | 
| 
       20 
     | 
    
         
            -
                  if apply_additional &&  
     | 
| 
      
 20 
     | 
    
         
            +
                  if apply_additional && keyword?('additionalProperties')
         
     | 
| 
       21 
21 
     | 
    
         
             
                    yield subschema(['additionalProperties'])
         
     | 
| 
       22 
22 
     | 
    
         
             
                  end
         
     | 
| 
       23 
23 
     | 
    
         
             
                end
         
     | 
| 
         @@ -9,32 +9,5 @@ module JSI 
     | 
|
| 
       9 
9 
     | 
    
         
             
                autoload :Items, 'jsi/schema/application/child_application/items'
         
     | 
| 
       10 
10 
     | 
    
         
             
                autoload :Contains, 'jsi/schema/application/child_application/contains'
         
     | 
| 
       11 
11 
     | 
    
         
             
                autoload :Properties, 'jsi/schema/application/child_application/properties'
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
                # a set of child applicator subschemas of this schema which apply to the child of the given instance
         
     | 
| 
       14 
     | 
    
         
            -
                # on the given token.
         
     | 
| 
       15 
     | 
    
         
            -
                #
         
     | 
| 
       16 
     | 
    
         
            -
                # @param token [Object] the array index or object property name for the child instance
         
     | 
| 
       17 
     | 
    
         
            -
                # @param instance [Object] the instance to check any child applicators against
         
     | 
| 
       18 
     | 
    
         
            -
                # @return [JSI::SchemaSet] child applicator subschemas of this schema for the given token
         
     | 
| 
       19 
     | 
    
         
            -
                #   of the instance
         
     | 
| 
       20 
     | 
    
         
            -
                def child_applicator_schemas(token, instance)
         
     | 
| 
       21 
     | 
    
         
            -
                  SchemaSet.new(each_child_applicator_schema(token, instance))
         
     | 
| 
       22 
     | 
    
         
            -
                end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                # yields each child applicator subschema (from properties, items, etc.) which applies to the child of
         
     | 
| 
       25 
     | 
    
         
            -
                # the given instance on the given token.
         
     | 
| 
       26 
     | 
    
         
            -
                #
         
     | 
| 
       27 
     | 
    
         
            -
                # @param (see #child_applicator_schemas)
         
     | 
| 
       28 
     | 
    
         
            -
                # @yield [JSI::Schema]
         
     | 
| 
       29 
     | 
    
         
            -
                # @return [nil, Enumerator] an Enumerator if invoked without a block; otherwise nil
         
     | 
| 
       30 
     | 
    
         
            -
                def each_child_applicator_schema(token, instance, &block)
         
     | 
| 
       31 
     | 
    
         
            -
                  return to_enum(__method__, token, instance) unless block
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                  if schema_content.respond_to?(:to_hash)
         
     | 
| 
       34 
     | 
    
         
            -
                    internal_child_applicate_keywords(token, instance, &block)
         
     | 
| 
       35 
     | 
    
         
            -
                  end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                  nil
         
     | 
| 
       38 
     | 
    
         
            -
                end
         
     | 
| 
       39 
12 
     | 
    
         
             
              end
         
     | 
| 
       40 
13 
     | 
    
         
             
            end
         
     | 
| 
         @@ -4,7 +4,7 @@ module JSI 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::InplaceApplication::Dependencies
         
     | 
| 
       5 
5 
     | 
    
         
             
                # @private
         
     | 
| 
       6 
6 
     | 
    
         
             
                def internal_applicate_dependencies(instance, visited_refs, &block)
         
     | 
| 
       7 
     | 
    
         
            -
                  if  
     | 
| 
      
 7 
     | 
    
         
            +
                  if keyword?('dependencies')
         
     | 
| 
       8 
8 
     | 
    
         
             
                    value = schema_content['dependencies']
         
     | 
| 
       9 
9 
     | 
    
         
             
                    # This keyword's value MUST be an object. Each property specifies a dependency.  Each dependency
         
     | 
| 
       10 
10 
     | 
    
         
             
                    # value MUST be an array or a valid JSON Schema.
         
     | 
| 
         @@ -2,7 +2,6 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module JSI
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::InplaceApplication::Draft04
         
     | 
| 
       5 
     | 
    
         
            -
                include Schema::Application::InplaceApplication
         
     | 
| 
       6 
5 
     | 
    
         
             
                include Schema::Application::InplaceApplication::Ref
         
     | 
| 
       7 
6 
     | 
    
         
             
                include Schema::Application::InplaceApplication::Dependencies
         
     | 
| 
       8 
7 
     | 
    
         
             
                include Schema::Application::InplaceApplication::SomeOf
         
     | 
| 
         @@ -2,7 +2,6 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module JSI
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::InplaceApplication::Draft06
         
     | 
| 
       5 
     | 
    
         
            -
                include Schema::Application::InplaceApplication
         
     | 
| 
       6 
5 
     | 
    
         
             
                include Schema::Application::InplaceApplication::Ref
         
     | 
| 
       7 
6 
     | 
    
         
             
                include Schema::Application::InplaceApplication::Dependencies
         
     | 
| 
       8 
7 
     | 
    
         
             
                include Schema::Application::InplaceApplication::SomeOf
         
     | 
| 
         @@ -2,7 +2,6 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module JSI
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::InplaceApplication::Draft07
         
     | 
| 
       5 
     | 
    
         
            -
                include Schema::Application::InplaceApplication
         
     | 
| 
       6 
5 
     | 
    
         
             
                include Schema::Application::InplaceApplication::Ref
         
     | 
| 
       7 
6 
     | 
    
         
             
                include Schema::Application::InplaceApplication::Dependencies
         
     | 
| 
       8 
7 
     | 
    
         
             
                include Schema::Application::InplaceApplication::IfThenElse
         
     | 
| 
         @@ -4,13 +4,13 @@ module JSI 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::InplaceApplication::IfThenElse
         
     | 
| 
       5 
5 
     | 
    
         
             
                # @private
         
     | 
| 
       6 
6 
     | 
    
         
             
                def internal_applicate_ifthenelse(instance, visited_refs, &block)
         
     | 
| 
       7 
     | 
    
         
            -
                  if  
     | 
| 
      
 7 
     | 
    
         
            +
                  if keyword?('if')
         
     | 
| 
       8 
8 
     | 
    
         
             
                    if subschema(['if']).instance_valid?(instance)
         
     | 
| 
       9 
     | 
    
         
            -
                      if  
     | 
| 
      
 9 
     | 
    
         
            +
                      if keyword?('then')
         
     | 
| 
       10 
10 
     | 
    
         
             
                        subschema(['then']).each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
         
     | 
| 
       11 
11 
     | 
    
         
             
                      end
         
     | 
| 
       12 
12 
     | 
    
         
             
                    else
         
     | 
| 
       13 
     | 
    
         
            -
                      if  
     | 
| 
      
 13 
     | 
    
         
            +
                      if keyword?('else')
         
     | 
| 
       14 
14 
     | 
    
         
             
                        subschema(['else']).each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
         
     | 
| 
       15 
15 
     | 
    
         
             
                      end
         
     | 
| 
       16 
16 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -4,8 +4,8 @@ module JSI 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::InplaceApplication::Ref
         
     | 
| 
       5 
5 
     | 
    
         
             
                # @private
         
     | 
| 
       6 
6 
     | 
    
         
             
                def internal_applicate_ref(instance, visited_refs, throw_done: false, &block)
         
     | 
| 
       7 
     | 
    
         
            -
                  if schema_content['$ref'].respond_to?(:to_str)
         
     | 
| 
       8 
     | 
    
         
            -
                    ref =  
     | 
| 
      
 7 
     | 
    
         
            +
                  if keyword?('$ref') && schema_content['$ref'].respond_to?(:to_str)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    ref = schema_ref('$ref')
         
     | 
| 
       9 
9 
     | 
    
         
             
                    unless visited_refs.include?(ref)
         
     | 
| 
       10 
10 
     | 
    
         
             
                      ref.deref_schema.each_inplace_applicator_schema(instance, visited_refs: visited_refs + [ref], &block)
         
     | 
| 
       11 
11 
     | 
    
         
             
                      if throw_done
         
     | 
| 
         @@ -4,24 +4,39 @@ module JSI 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module Schema::Application::InplaceApplication::SomeOf
         
     | 
| 
       5 
5 
     | 
    
         
             
                # @private
         
     | 
| 
       6 
6 
     | 
    
         
             
                def internal_applicate_someOf(instance, visited_refs, &block)
         
     | 
| 
       7 
     | 
    
         
            -
                  if schema_content['allOf'].respond_to?(:to_ary)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  if keyword?('allOf') && schema_content['allOf'].respond_to?(:to_ary)
         
     | 
| 
       8 
8 
     | 
    
         
             
                    schema_content['allOf'].each_index do |i|
         
     | 
| 
       9 
9 
     | 
    
         
             
                      subschema(['allOf', i]).each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
         
     | 
| 
       10 
10 
     | 
    
         
             
                    end
         
     | 
| 
       11 
11 
     | 
    
         
             
                  end
         
     | 
| 
       12 
     | 
    
         
            -
                  if schema_content['anyOf'].respond_to?(:to_ary)
         
     | 
| 
       13 
     | 
    
         
            -
                    schema_content['anyOf'].each_index  
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                       
     | 
| 
      
 12 
     | 
    
         
            +
                  if keyword?('anyOf') && schema_content['anyOf'].respond_to?(:to_ary)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    anyOf = schema_content['anyOf'].each_index.map { |i| subschema(['anyOf', i]) }
         
     | 
| 
      
 14 
     | 
    
         
            +
                    validOf = anyOf.select { |schema| schema.instance_valid?(instance) }
         
     | 
| 
      
 15 
     | 
    
         
            +
                    if !validOf.empty?
         
     | 
| 
      
 16 
     | 
    
         
            +
                      applicators = validOf
         
     | 
| 
      
 17 
     | 
    
         
            +
                    else
         
     | 
| 
      
 18 
     | 
    
         
            +
                      # invalid application: if none of the anyOf were valid, we apply them all
         
     | 
| 
      
 19 
     | 
    
         
            +
                      applicators = anyOf
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    applicators.each do |applicator|
         
     | 
| 
      
 23 
     | 
    
         
            +
                      applicator.each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
         
     | 
| 
       17 
24 
     | 
    
         
             
                    end
         
     | 
| 
       18 
25 
     | 
    
         
             
                  end
         
     | 
| 
       19 
     | 
    
         
            -
                  if schema_content['oneOf'].respond_to?(:to_ary)
         
     | 
| 
       20 
     | 
    
         
            -
                     
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
                  if keyword?('oneOf') && schema_content['oneOf'].respond_to?(:to_ary)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    oneOf_idxs = schema_content['oneOf'].each_index
         
     | 
| 
      
 28 
     | 
    
         
            +
                    subschema_idx_valid = Hash.new { |h, i| h[i] = subschema(['oneOf', i]).instance_valid?(instance) }
         
     | 
| 
      
 29 
     | 
    
         
            +
                    # count up to 2 `oneOf` subschemas which `instance` validates against
         
     | 
| 
      
 30 
     | 
    
         
            +
                    nvalid = oneOf_idxs.inject(0) { |n, i| n <= 1 && subschema_idx_valid[i] ? n + 1 : n }
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if nvalid == 1
         
     | 
| 
      
 32 
     | 
    
         
            +
                      applicator_idxs = oneOf_idxs.select { |i| subschema_idx_valid[i] }
         
     | 
| 
      
 33 
     | 
    
         
            +
                    else
         
     | 
| 
      
 34 
     | 
    
         
            +
                      # invalid application: if none or multiple of the oneOf were valid, we apply them all
         
     | 
| 
      
 35 
     | 
    
         
            +
                      applicator_idxs = oneOf_idxs
         
     | 
| 
       22 
36 
     | 
    
         
             
                    end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    applicator_idxs.each do |i|
         
     | 
| 
      
 39 
     | 
    
         
            +
                      subschema(['oneOf', i]).each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
         
     | 
| 
       25 
40 
     | 
    
         
             
                    end
         
     | 
| 
       26 
41 
     | 
    
         
             
                  end
         
     | 
| 
       27 
42 
     | 
    
         
             
                end
         
     | 
| 
         @@ -10,37 +10,5 @@ module JSI 
     | 
|
| 
       10 
10 
     | 
    
         
             
                autoload :SomeOf, 'jsi/schema/application/inplace_application/someof'
         
     | 
| 
       11 
11 
     | 
    
         
             
                autoload :IfThenElse, 'jsi/schema/application/inplace_application/ifthenelse'
         
     | 
| 
       12 
12 
     | 
    
         
             
                autoload :Dependencies, 'jsi/schema/application/inplace_application/dependencies'
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                # a set of inplace applicator schemas of this schema (from $ref, allOf, etc.) which apply to the
         
     | 
| 
       15 
     | 
    
         
            -
                # given instance.
         
     | 
| 
       16 
     | 
    
         
            -
                #
         
     | 
| 
       17 
     | 
    
         
            -
                # the returned set will contain this schema itself, unless this schema contains a $ref keyword.
         
     | 
| 
       18 
     | 
    
         
            -
                #
         
     | 
| 
       19 
     | 
    
         
            -
                # @param instance [Object] the instance to check any applicators against
         
     | 
| 
       20 
     | 
    
         
            -
                # @return [JSI::SchemaSet] matched applicator schemas
         
     | 
| 
       21 
     | 
    
         
            -
                def inplace_applicator_schemas(instance)
         
     | 
| 
       22 
     | 
    
         
            -
                  SchemaSet.new(each_inplace_applicator_schema(instance))
         
     | 
| 
       23 
     | 
    
         
            -
                end
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                # yields each inplace applicator schema which applies to the given instance.
         
     | 
| 
       26 
     | 
    
         
            -
                #
         
     | 
| 
       27 
     | 
    
         
            -
                # @param instance (see #inplace_applicator_schemas)
         
     | 
| 
       28 
     | 
    
         
            -
                # @param visited_refs [Enumerable<JSI::Schema::Ref>]
         
     | 
| 
       29 
     | 
    
         
            -
                # @yield [JSI::Schema]
         
     | 
| 
       30 
     | 
    
         
            -
                # @return [nil, Enumerator] an Enumerator if invoked without a block; otherwise nil
         
     | 
| 
       31 
     | 
    
         
            -
                def each_inplace_applicator_schema(instance, visited_refs: [], &block)
         
     | 
| 
       32 
     | 
    
         
            -
                  return to_enum(__method__, instance, visited_refs: visited_refs) unless block
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                  catch(:jsi_application_done) do
         
     | 
| 
       35 
     | 
    
         
            -
                    if schema_content.respond_to?(:to_hash)
         
     | 
| 
       36 
     | 
    
         
            -
                      internal_inplace_applicate_keywords(instance, visited_refs, &block)
         
     | 
| 
       37 
     | 
    
         
            -
                    else
         
     | 
| 
       38 
     | 
    
         
            -
                      # self is the only applicator schema if there are no keywords
         
     | 
| 
       39 
     | 
    
         
            -
                      yield self
         
     | 
| 
       40 
     | 
    
         
            -
                    end
         
     | 
| 
       41 
     | 
    
         
            -
                  end
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                  nil
         
     | 
| 
       44 
     | 
    
         
            -
                end
         
     | 
| 
       45 
13 
     | 
    
         
             
              end
         
     | 
| 
       46 
14 
     | 
    
         
             
            end
         
     | 
    
        data/lib/jsi/schema/draft04.rb
    CHANGED
    
    
    
        data/lib/jsi/schema/draft06.rb
    CHANGED