;;; Shared record conventions for Scheme-facing Dat APIs. ;;; A record is (tag (field . value) ...); payload bytes stay bytevectors. (define (dat:record? value . wanted-tag) (and (pair? value) (symbol? (car value)) (or (null? wanted-tag) (eq? (car value) (car wanted-tag))) (let loop ((fields (cdr value)) (seen '())) (if (null? fields) #t (and (pair? fields) (pair? (car fields)) (symbol? (caar fields)) (not (memq (caar fields) seen)) (loop (cdr fields) (cons (caar fields) seen))))))) (define (dat:record-ref record field . fallback) (if (not (dat:record? record)) (error 'wrong-type-arg "expected a Dat record" record) (if (not (symbol? field)) (error 'wrong-type-arg "record field name must be a symbol" field) (let ((entry (assq field (cdr record)))) (if entry (cdr entry) (if (pair? fallback) (car fallback) #f)))))) (define (dat:record-set record field value) (if (not (dat:record? record)) (error 'wrong-type-arg "expected a Dat record" record) (if (not (symbol? field)) (error 'wrong-type-arg "record field name must be a symbol" field) (let loop ((fields (cdr record)) (reversed '()) (found #f)) (if (null? fields) (cons (car record) (reverse (if found reversed (cons (cons field value) reversed)))) (let ((entry (car fields))) (if (eq? (car entry) field) (loop (cdr fields) (cons (cons field value) reversed) #t) (loop (cdr fields) (cons entry reversed) found)))))))) (provide 'dat:record)