 quoted-string )
;;                         *expect-params ]
;; expect-params = ";" token [ "=" ( token | quoted-string ) ]
;;
(declare-param-list-header! "Expect")

;; From = mailbox
;;
;; Should be an email address; we just pass on the string as-is.
;;
(declare-opaque-header! "From")

;; Host = host [ ":" port ]
;; 
(declare-header! "Host"
  (lambda (str)
    (let* ((rbracket (string-index str #\]))
           (colon (string-index str #\: (or rbracket 0)))
           (host (cond
                  (rbracket
                   (unless (eqv? (string-ref str 0) #\[)
                     (bad-header 'host str))
                   (substring str 1 rbracket))
                  (colon
                   (substring str 0 colon))
                  (else
                   str)))
           (port (and colon
                      (parse-non-negative-integer str (1+ colon)))))
      (cons host port)))
  (lambda (val)
    (match val
      (((? string?) . (or #f (? non-negative-integer?))) #t)
      (_ #f)))
  (lambda (val port)
    (match val
      ((host-name . host-port)
       (cond
        ((string-index host-name #\:)
         (put-char port #\[)
         (put-string port host-name)
         (put-char port #\]))
        (else
         (put-string port host-name)))
       (when host-port
         (put-char port #\:)
         (put-non-negative-integer port host-port))))))

;; If-Match = ( "*" | 1#entity-tag )
;;
(declare-entity-tag-list-header! "If-Match")

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

;; If-None-Match = ( "*" | 1#entity-tag )
;;
(declare-entity-tag-list-header! "If-None-Match")

;; If-Range = ( entity-tag | HTTP-date )
;;
(declare-header! "If-Range"
  (lambda (str)
    (if (or (string-prefix? "\"" str)
            (string-prefix? "W/" str))
        (parse-entity-tag str)
        (parse-date str)))
  (lambda (val)
    (or (date? val) (entity-tag? val)))
  (lambda (val port)
    (if (date? val)
        (write-date val port)
        (put-entity-tag port val))))

;; If-Unmodified-Since = HTTP-date
;;
(declare-date-header! "If-Unmodified-Since")

;; Max-Forwards = 1*DIGIT
;;
(declare-integer-header! "Max-Forwards")

;; Proxy-Authorization = credentials
;;
(declare-credentials-header! "Proxy-Authorization")

;; Range = "Range" ":" ranges-specifier
;; ranges-specifier = byte-ranges-specifier
;; byte-ranges-specifier = bytes-unit "=" byte-range-set
;; byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
;; byte-range-spec = first-byte-pos "-" [last-byte-pos]
;; first-byte-pos = 1*DIGIT
;; last-byte-pos = 1*DIGIT
;; suffix-byte-range-spec = "-" suffix-length
;; suffix-length = 1*DIGIT
;;
(declare-header! "Range"
  (lambda (str)
    (unless (string-prefix? "bytes=" str)
      (bad-header 'range str))
    (cons
     'bytes
     (map (lambda (x)
            (let ((dash (string-index x #\-)))
              (cond
               ((not dash)
                (bad-header 'range str))
               ((zero? dash)
                (cons #f (parse-non-negative-integer x 1)))
               ((= dash (1- (string-length x)))
                (cons (parse-non-negative-integer x 0 dash) #f))
               (else
                (cons (parse-non-negative-integer x 0 dash)
                      (parse-non-negative-integer x (1+ dash)))))))
          (string-split (substring str 6) #\,))))
  (lambda (val)
    (match val
      (((? symbol?)
        (or (#f                        . (? non-negative-integer?))
            ((? non-negative-integer?) . (? non-negative-integer?))
            ((? non-negative-integer?) . #f))
        ...) #t)
      (_ #f)))
  (lambda (val port)
    (match val
      ((unit . ranges)
       (put-symbol port unit)
       (put-char port #\=)
       (put-list
        port ranges
        (lambda (port range)
          (match range
            ((start . end)
             (when start (put-non-negative-integer port start))
             (put-char port #\-)
             (when end (put-non-negative-integer port end)))))
        ",")))))

;; Referer = URI-reference
;;
(declare-uri-reference-header! "Referer")

;; TE = #( t-codings )
;; t-codings = "trailers" | ( transfer-extension [ accept-params ] )
;;
(declare-param-list-header! "TE")

;; User-Agent = 1*( product | comment )
;;
(declare-opaque-header! "User-Agent")


