|
78 | 78 | validator-context-lint-mode?
|
79 | 79 | validator-context:add-path!
|
80 | 80 | validator-context:detatch-report!
|
81 |
| - validator-context:marks |
82 |
| - validator-context:mark! |
83 | 81 | validator-context:mark-element!
|
84 |
| - validator-context:update-difference! |
85 |
| - validator-context:marked? |
| 82 | + validator-context:update-marks! |
86 | 83 | validator-context:marked-element?
|
87 | 84 | validator-context:unevaluated?
|
88 | 85 | validator-context:set-dynamic-context!
|
|
102 | 99 | (srfi :13 strings)
|
103 | 100 | (srfi :39 parameters)
|
104 | 101 | (srfi :117 list-queues)
|
| 102 | + (srfi :126 hashtables) |
105 | 103 | (text json pointer)
|
106 | 104 | (text json schema version))
|
107 | 105 |
|
|
338 | 336 | (fields path
|
339 | 337 | parent
|
340 | 338 | reports
|
341 |
| - marks |
342 | 339 | dynamic-contexts
|
343 | 340 | evaluating-scopes ;; schema-ids
|
344 | 341 | evaluating-schemas ;; schema
|
|
347 | 344 | (make-raw-validator-context
|
348 | 345 | "/" #f
|
349 | 346 | (list-queue)
|
350 |
| - ;; relay on the fact that JSON must not have duplicate keys |
351 |
| - (make-hashtable equal-hash equal?) |
352 | 347 | (make-hashtable equal-hash equal?)
|
353 | 348 | (list-queue)
|
354 | 349 | (list-queue)
|
|
367 | 362 | (build-validation-path base path)
|
368 | 363 | context
|
369 | 364 | (validator-context-reports context)
|
370 |
| - (validator-context-marks context) |
371 | 365 | (validator-context-dynamic-contexts context)
|
372 | 366 | (validator-context-evaluating-scopes context)
|
373 | 367 | (validator-context-evaluating-schemas context)
|
|
378 | 372 | (validator-context-path context)
|
379 | 373 | context
|
380 | 374 | (list-queue)
|
381 |
| - (validator-context-marks context) |
382 | 375 | (validator-context-dynamic-contexts context)
|
383 | 376 | (validator-context-evaluating-scopes context)
|
384 | 377 | (validator-context-evaluating-schemas context)
|
|
399 | 392 | (define (validator-context:reports context)
|
400 | 393 | (list-queue-list (validator-context-reports context)))
|
401 | 394 |
|
402 |
| -(define (validator-context:mark! context obj schema) |
403 |
| - ;; (newline) |
404 |
| - ;; (display obj) (newline) |
405 |
| - ;; (display (schema-context-schema schema)) (newline) |
406 |
| - ;; (for-each (lambda (s) (display "--> ") (display s) (newline)) |
407 |
| - ;; (list-queue-list (validator-context-evaluating-schemas context))) |
408 |
| - (let ((mark (validator-context-marks context))) |
409 |
| - (hashtable-update! mark obj |
410 |
| - (lambda (v) |
411 |
| - (cond ((assq schema v) v) |
412 |
| - (else (cons (cons schema (list-queue)) v)))) |
413 |
| - '()))) |
414 | 395 | (define (validator-context:mark-element! context obj element schema success?)
|
415 |
| - (let ((mark (validator-context-marks context))) |
416 |
| - (hashtable-update! mark obj |
417 |
| - (lambda (v) |
418 |
| - (cond ((assq schema v) => |
419 |
| - (lambda (slot) |
420 |
| - (list-queue-add-front! (cdr slot) (cons element success?))))) |
421 |
| - v) |
422 |
| - '()) |
423 |
| - success?)) |
424 |
| - |
425 |
| -(define (validator-context:update-difference! context obj snapshot success?) |
426 |
| - (define (swap-marks! q base diff) |
427 |
| - (list-queue-clear! q) |
428 |
| - (for-each (lambda (v) (list-queue-add-back! q v)) base) |
429 |
| - ;; strip out failed validation |
430 |
| - ;; NB: this is for unevaludated with `not not` case |
431 |
| - ;; I think it should be invalid test case, but it's listed |
432 |
| - ;; in the official test suite, so no argue. |
433 |
| - (for-each (lambda (v) |
434 |
| - (when success? |
435 |
| - (set-cdr! v #t) |
436 |
| - (list-queue-add-back! q v))) diff)) |
437 |
| - (let ((slots (hashtable-ref (validator-context-marks context) obj '()))) |
438 |
| - (for-each (lambda (slot) |
439 |
| - (let ((q (cdr slot))) |
440 |
| - (cond ((memq (car slot) snapshot) => |
441 |
| - (lambda (base) |
442 |
| - (let* ((marks (list-queue-list q)) |
443 |
| - (diff (drop-right marks (length base)))) |
444 |
| - (swap-marks! q base diff)))) |
445 |
| - (else |
446 |
| - (swap-marks! q '() (list-queue-list q)))))) |
447 |
| - slots) |
| 396 | + (define target-schema (schema-context-schema schema)) |
| 397 | + (let-values (((schema marks) (validator-context:evaluating-schema context))) |
| 398 | + (when (eq? target-schema schema) |
| 399 | + (let ((v (cons* schema element success?))) |
| 400 | + (hashtable-update! marks obj (lambda (r) (cons v r)) '())))) |
| 401 | + success?) |
| 402 | + |
| 403 | +(define (validator-context:update-marks! context obj schema success?) |
| 404 | + (define target-schema (schema-context-schema schema)) |
| 405 | + (define (flip-result v) |
| 406 | + (filter-map (lambda (s) |
| 407 | + (cond ((eq? target-schema (car s)) |
| 408 | + (cond (success? (set-cdr! (cdr s) success?) s) |
| 409 | + (else #f))) |
| 410 | + (else s))) v)) |
| 411 | + (let-values (((schema marks) (validator-context:evaluating-schema context))) |
| 412 | + (hashtable-update! marks obj flip-result '()) |
448 | 413 | success?))
|
449 | 414 |
|
450 |
| -(define (validator-context:marks context obj) |
451 |
| - (define (->snapshot slot) |
452 |
| - ;; convert (schema (e result) ...) |
453 |
| - (cons (car slot) (list-queue-list (cdr slot)))) |
454 |
| - |
455 |
| - (let ((mark (validator-context-marks context))) |
456 |
| - (map ->snapshot (hashtable-ref mark obj '())))) |
457 |
| - |
458 |
| -(define (validator-context:marked? context obj schema-context) |
459 |
| - (let ((slots (hashtable-ref (validator-context-marks context) obj '()))) |
460 |
| - (cond ((assq schema-context slots)) |
461 |
| - (else #f)))) |
462 |
| - |
463 | 415 | (define (validator-context:marked-element? context obj element schema-context)
|
464 |
| - (let ((slots (hashtable-ref (validator-context-marks context) obj '()))) |
465 |
| - (cond ((assq schema-context slots) => |
466 |
| - (lambda (slot) (assoc element (list-queue-list (cdr slot))))) |
467 |
| - (else #f)))) |
| 416 | + (define target-schema (schema-context-schema schema-context)) |
| 417 | + (let-values (((schema marks) (validator-context:evaluating-schema context))) |
| 418 | + (let ((slots (hashtable-ref marks obj '()))) |
| 419 | + (cond ((find (lambda (v) |
| 420 | + (and (eq? (car v) target-schema) (equal? (cadr v) element))) |
| 421 | + slots) #t) |
| 422 | + (else #f))))) |
468 | 423 |
|
469 | 424 | (define (validator-context:unevaluated? context obj element schema-context)
|
470 |
| - (define (collect element elements) |
471 |
| - (define (check r element v) (if (equal? (car v) element) (cons v r) r)) |
472 |
| - (do ((elements elements (cdr elements)) |
473 |
| - (r '() (check r element (car elements)))) |
474 |
| - ((null? elements) r))) |
475 |
| - |
476 |
| - (define (check slot) |
477 |
| - (let ((marked-context (car slot))) |
478 |
| - (or (not (schema-context:same-root? schema-context marked-context)) |
479 |
| - ;; We need to exclude cousins, so check subschema |
480 |
| - (subschema? (schema-context-schema schema-context) |
481 |
| - (schema-context-schema marked-context))))) |
482 |
| - |
483 |
| - (let ((e* (append-map (lambda (s) (list-queue-list (cdr s))) |
484 |
| - (filter check |
485 |
| - (hashtable-ref (validator-context-marks context) obj '()))))) |
486 |
| - ;; because of allOf, anyOf or oneOf applicators, the elements may contain |
487 |
| - ;; multiple of the same element. So, collect everything and check if |
488 |
| - ;; there's a successful evaluation or not |
489 |
| - (not (null? (filter-map cdr (collect element e*)))))) |
| 425 | + (let-values (((schema marks) (validator-context:evaluating-schema context))) |
| 426 | + (and (eq? schema (schema-context-schema schema-context)) |
| 427 | + (cond ((hashtable-ref marks obj #f) => |
| 428 | + (lambda (v*) |
| 429 | + (find (lambda (v) |
| 430 | + (and (cddr v) (equal? (cadr v) element))) v*))) |
| 431 | + (else #f))))) |
490 | 432 |
|
491 | 433 | (define (validator-context:set-dynamic-context! context schema-context anchor)
|
492 | 434 | (let ((root (schema-context-root schema-context))
|
|
520 | 462 |
|
521 | 463 | (define (validator-context:push-schema! context schema)
|
522 | 464 | (let ((queue (validator-context-evaluating-schemas context)))
|
523 |
| - (list-queue-add-front! queue schema))) |
| 465 | + (list-queue-add-front! queue (cons schema (make-eq-hashtable))))) |
524 | 466 |
|
525 | 467 | (define (validator-context:pop-scope! context)
|
526 | 468 | (let ((queue (validator-context-evaluating-scopes context)))
|
527 | 469 | (list-queue-remove-front! queue)))
|
528 | 470 |
|
529 | 471 | (define (validator-context:pop-schema! context)
|
530 |
| - (let ((queue (validator-context-evaluating-schemas context))) |
531 |
| - (list-queue-remove-front! queue))) |
| 472 | + (let* ((queue (validator-context-evaluating-schemas context)) |
| 473 | + (e (list-queue-remove-front! queue))) |
| 474 | + (unless (list-queue-empty? queue) |
| 475 | + (let ((ht (cdr (list-queue-front queue)))) |
| 476 | + (hashtable-walk (cdr e) |
| 477 | + ;; k = obj, v = (schema . element) |
| 478 | + ;; it's a bit redundant, but keep it like this for my convenience |
| 479 | + (lambda (k v) |
| 480 | + (hashtable-update! ht k (lambda (r) (append v r)) '()))))))) |
| 481 | + |
| 482 | +(define (validator-context:evaluating-schema context) |
| 483 | + (let ((v (list-queue-front (validator-context-evaluating-schemas context)))) |
| 484 | + (values (car v) (cdr v)))) |
532 | 485 |
|
533 | 486 | ;; Schema validator
|
534 | 487 | (define (update-cache! context validator)
|
|
702 | 655 | ((eq? scope-context child-context))
|
703 | 656 | (else (in-scope? scope-context (schema-context-parent child-context)))))
|
704 | 657 |
|
705 |
| -(define (subschema? root-schema schema) |
706 |
| - (and (subschema-depth root-schema schema) #t)) |
707 |
| -(define (subschema-depth root-schema schema) |
708 |
| - (define (rec root-schema schema depth) |
709 |
| - ;; we don't modify the schema, so `eq?` works. |
710 |
| - (cond ((eq? root-schema schema) depth) |
711 |
| - ((vector? root-schema) |
712 |
| - ;; For now DFS, might be better to do BFS |
713 |
| - (let ((len (vector-length root-schema))) |
714 |
| - (let loop ((i 0)) |
715 |
| - (cond ((= i len) #f) |
716 |
| - ((rec (cdr (vector-ref root-schema i)) schema (+ depth 1))) |
717 |
| - (else (loop (+ i 1))))))) |
718 |
| - ((list? root-schema) |
719 |
| - (exists (lambda (r) (rec r schema (+ depth 1))) root-schema)) |
720 |
| - (else #f))) |
721 |
| - (rec root-schema schema 0)) |
722 |
| - |
723 | 658 | (define (build-schema-path base child) (cons child base))
|
724 | 659 | (define (boolean->validator b) (lambda (e ctx) b))
|
725 | 660 |
|
|
0 commit comments