Sha256: c264b79670b059245a532c0e41a1fbced062ebd771571db21208ff595970ef64
Contents?: true
Size: 1.95 KB
Versions: 1
Compression:
Stored size: 1.95 KB
Contents
module DataModel module Scanner extend self def scan(schema, registry = Registry.instance) start = { validator: nil, property: nil, state: :start } result = schema.each_with_index.reduce(start) do |context, (token, pos)| context => {state:, validator:, property:} peek = schema[pos + 1] # detect named validators, a name could be any type so cannot be detected # by ruby type and state. detect name by ensuring we are at the start # of scanning, and the next element is a valid type. if state == :start && registry.type?(peek) context.merge( property: token, state: :named, ) else # with the special case of a name aside, we can detect the meaning # of further tokens by their type and scanner state case token when Symbol unless [:start, :named].include?(state) raise "got a symbol at pos #{pos}, but validator already defined" end unless registry.type?(token) raise "expected a type in pos #{pos}, but found #{token.inspect} which is not a registered type" end context.merge( validator: registry.type(token, property), state: :defined, ) when Hash unless state == :defined raise "got a hash at pos #{pos}, but state is not :defined (#{state.inspect})" end context.merge( validator: validator.merge(config: token), state: :configured, ) when Array unless [:defined, :configured].include?(state) raise "#{schema.inspect} at pos #{pos}: expected (String | Hash | Symbol | Array), got #{token.class.name}" end children = token.map { |s| scan(s, registry) } context.merge( validator: validator.merge(children:), state: :complete, ) else raise "got token #{token.inspect} at position #{pos} which was unexpected given the scanner was in a state of #{state}" end end end result.fetch(:validator) end end end
Version data entries
1 entries across 1 versions & 1 rubygems
Version | Path |
---|---|
data_model-0.0.1 | lib/data_model/scanner.rb |