ons
               (parse-non-negative-integer str 6 dash)
               (parse-non-negative-integer str (1+ dash) slash)))
             ((string= str "*" 6 slash)
              '*)
             (else
              (bad-header 'content-range str)))
            (if (string= str "*" (1+ slash))
                '*
                (parse-non-negative-integer str (1+ slash))))))
  (lambda (val)
    (match val
      (((? symbol?)
        (or '* ((? non-negative-integer?) . (? non-negative-integer?)))
        (or '* (? non-negative-integer?)))
       #t)
      (_ #f)))
  (lambda (val port)
    (match val
      ((unit range instance-length)
       (put-symbol port unit)
       (put-char port #\space)
       (match range
         ('*
          (put-char port #\*))
         ((start . end)
          (put-non-negative-integer port start)
          (put-char port #\-)
          (put-non-negative-integer port end)))
       (put-char port #\/)
       (match instance-length
         ('* (put-char port #\*))
         (len (put-non-negative-integer port len)))))))

;; Content-Type = media-type
;;
(declare-header! "Content-Type"
  (lambda (str)
    (let ((parts (string-split str #\;)))
      (cons (parse-media-type (car parts))
            (map (lambda (x)
                   (let ((eq (string-index x #\=)))
                     (unless (and eq (= eq (string-rindex x #\=)))
                       (bad-header 'content-type str))
                     (cons
                      (string->symbol
                       (string-trim x char-set:whitespace 0 eq))
                      (string-trim-right x char-set:whitespace (1+ eq)))))
                 (cdr parts)))))
  (lambda (val)
    (match val
      (((? symbol?) ((? symbol?) . (? string?)) ...) #t)
      (_ #f)))
  (lambda (val port)
    (match val
      ((type . args)
       (put-symbol port type)
       (match args
         (() (values))
         (args
          (put-string port ";")
          (put-list
           port args
           (lambda (port pair)
             (match pair
               ((k . v)
                (put-symbol port k)
                (put-char port #\=)
                (put-string port v))))
           ";")))))))

;; Expires = HTTP-date
;;
(define *date-in-the-past* (parse-date "Thu, 01 Jan 1970 00:00:00 GMT"))

(declare-header! "Expires"
  (lambda (str)
    (if (member str '("0" "-1"))
        *date-in-the-past*
        (parse-date str)))
  date?
  write-date)

;; Last-Modified = HTTP-date
;;
(declare-date-header! "Last-Modified")


