This version is still in development and is not considered stable yet. For the latest stable version, please use SFV 0.1!

ol.sfv

RFC 9651 Structured Field Values for HTTP.

See the project website for info on motivation and design: https://github.com/outskirtslabs/sfv

This ns provides parsing and serialization of Structured Fields containing Items, Lists, and Dictionaries with Parameters. Returns precise AST representations that round-trip byte-for-byte with RFC 9651 strings.

Conventions

  • s-or-bytes: Input string or byte array (decoded as ascii) containing HTTP field value

  • field-type: One of :item, :list, or :dict specifying the top-level structure

  • :bare: The raw value within an Item (Integer, Decimal, String, Token, Byte Sequence, Boolean, Date, or Display String)

Primitive Types

Each Item’s :bare is one of these RFC 9651 types:

SFV type Header AST example Clojure type (:value)

Integer

42, -17, 999999999999999

{:type :integer :value 1618884473}

long

Decimal

3.14, -0.5

{:type :decimal :value 3.14M}

BigDecimal

String

" hello world "

{:type :string :value " hello "}

java.lang.String

Token

simple-token

{:type :token :value " simple-token "}

String

Byte Sequence

:SGVsbG8=:

{:type :bytes :value <platform bytes>}

byte[]

Boolean

?1 / ?0

{:type :boolean :value true}

true / false

Date

@1659578233

{:type :date :value 1659578233}

epoch seconds as long

Display String

%" Gr%c3%bc%c3%9fe "

{:type :display :value " Grüße "}

String (percent-decoded, validated)

parse

(parse field-type s-or-bytes)

Parse a Structured Field of the given field-type.

Takes a field-type (:list, :dict, or :item) and a string or byte array. Returns an AST representation following RFC 9651.

(parse :item "42")
;; => {:type :item :bare {:type :integer :value 42} :params []}

(parse :dict "max-age=3600, must-revalidate")
;; => {:type :dict :entries [["max-age" {...}] ["must-revalidate" {...}]]}

parse-list

(parse-list s-or-bytes)

Parse a Structured Field List from s-or-bytes.

Returns a List AST with :type :list and :members vector containing Items and Inner Lists.

(parse-list "apple, pear;sweet=true, orange")
;; => {:type :list :members [...]}

parse-dict

(parse-dict s-or-bytes)

Parse a Structured Field Dictionary from s-or-bytes.

Returns a Dictionary AST with :type :dict and :entries as ordered key-value pairs. Each entry maps from a key to either an Item or Inner List.

(parse-dict "max-age=3600, must-revalidate")
;; => {:type :dict :entries [["max-age" {...}] ["must-revalidate" {...}]]}

parse-item

(parse-item s-or-bytes)

Parse a Structured Field Item from s-or-bytes.

Returns an Item AST with :type :item, :bare value, and :params Parameters. The bare value can be Integer, Decimal, String, Token, Byte Sequence, Boolean, Date, or Display String.

(parse-item "42")
;; => {:type :item :bare {:type :integer :value 42} :params []}

(parse-item "pear;sweet")
;; => {:type :item :bare {:type :token :value "pear"} :params `"sweet" {...}`}

serialize

(serialize x)

Serialize a Structured Field AST x to its string representation.

Takes any parsed AST (Item, List, or Dictionary) and returns the RFC 9651 string.

(serialize {:type :item :bare {:type :integer :value 42} :params []})
;; => "42"

(serialize-list {:type :list :members [...]})
;; => "apple, pear;sweet=true, orange"

(serialize-dict {:type :dict :entries [["max-age" {...}] ["must-revalidate" {...}]]})
;; => "max-age=3600, must-revalidate"

token

(token s)

token?

(token? x)

decimal

(decimal x)

decimal?

(decimal? x)

integer

(integer n)

integer?

(integer? x)

string

(string s)

string?

(string? x)

dstring

(dstring s)

dstring?

(dstring? x)

bytes

(bytes b)

bytes?

(bytes? x)

bool

(bool b)

bool?

(bool? x)

date

(date seconds)

date?

(date? x)

params

(params & kvs)

param-get

(param-get ps k)

param-keys

(param-keys ps)

item

(item bare)
(item bare ps)

item?

(item? x)

item-bare

(item-bare i)

item-params

(item-params i)

inner-list

(inner-list items)
(inner-list items ps)

inner-list?

(inner-list? x)

inner-items

(inner-items il)

inner-params

(inner-params il)

sf-list

(sf-list members)

sf-list?

(sf-list? x)

list-members

(list-members l)

sf-dict

(sf-dict entries)

sf-dict?

(sf-dict? x)

dict-keys

(dict-keys d)

dict-get

(dict-get d k)

dict→pairs

(dict->pairs d)

flag

(flag)
(flag ps)

flag?

(flag? x)