list.ss
#lang scheme
(require
 "packing.ss")

(define (cons/p car-packing cdr-packing)
  (make-packing
   (λ (in)
     (let* ([car-v ((packing-reader car-packing) in)]
            [cdr-v ((packing-reader cdr-packing) in)])
       (if (not (or (eof-object? car-v) (eof-object? cdr-v)))
           (cons car-v cdr-v)
           eof)))
   (λ (v out)
     ((packing-writer car-packing) (car v) out)
     ((packing-writer cdr-packing) (cdr v) out))
   (cons/c (packing-contract car-packing) (packing-contract cdr-packing))))

(define (list/p . packings)
  (make-packing
   (λ (in)
     (let/ec esc
       (for/list ([packing (in-list packings)]
                  #:when #t
                  [v (in-value ((packing-reader packing) in))])
         (if (not (eof-object? v))
             v
             (esc eof)))))
   (λ (v out)
     (for ([packing (in-list packings)] [v (in-list v)])
       ((packing-writer packing) v out)))
   (apply list/c (map packing-contract packings))))

(define (listof/p packing)
  (make-packing
   (λ (in)
     (port->list (packing-reader packing) in))
   (λ (v out)
     (for ([v (in-list v)])
       ((packing-writer packing) v out)))
   (listof (packing-contract packing))))

(define (dict/p key-packing value-packing)
  (wrap/p
   make-immutable-hash
   (curryr dict-map cons)
   (listof/p (cons/p key-packing value-packing))
   dict?))

(provide/contract
 [cons/p (-> packing? packing? packing?)]
 [list/p (->* () () #:rest (listof packing?) packing?)]
 [listof/p (-> packing? packing?)]
 [dict/p (-> packing? packing? packing?)])