{"size": 5940, "ext": "scrbl", "max_stars_repo_path": "scribblings/manual.scrbl", "max_stars_repo_name": "williewillus/racket-rfc8949", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "scribblings/manual.scrbl", "max_issues_repo_name": "williewillus/racket-rfc8949", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "scribblings/manual.scrbl", "max_forks_repo_name": "williewillus/racket-rfc8949", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 51.2068965517, "max_line_length": 257, "alphanum_fraction": 0.7316498316}
#lang scribble/manual
@(require (for-label racket))
@(require (for-label racket/undefined))
@(require (for-label "../main.rkt"))

@title{Concise Binary Object Representation}
@author{@author+email["Vincent Lee" "vincent@vincent-lee.net"]}

@defmodule[cbor]

This library implements serialization and deserialization routines for Concise Binary
Object Representation (CBOR), as defined in RFC 8949. The library takes in raw data
in the form of Racket data structures, outputting a serialized binary stream, and vice
versa.

@section{Usage}
@defproc[(cbor-write [config cbor-config?]
                     [v any/c]
                     [out output-port? (current-output-port)])
         void?]{
Writes the value @racket[v] to @racket[out].
The following @racket[v] are accepted:
@itemlist[
@item{Integers between -2@superscript{64} and 2@superscript{64} - 1, inclusive}
@item{@racket[#f] and @racket[#t]}
@item{Values @racket[equal?] to the value of @racket[(cbor-config-null-value config)]}
@item{@racket[undefined]}
@item{@racket[flonum?]s}
@item{@racket[bytes?] and @racket[string?]s}
@item{Lists and vectors of any item accepted by @racket[cbor-write]}
@item{Sequences of any item accepted by @racket[cbor-write]}
@item{Hashes of items accepted by @racket[cbor-write] (both the key and value)}
@item{Instances of @racket[cbor-tag]}
@item{Instances of @racket[cbor-simple-value]}
@item{Values which have an implementation for @racket[gen:cbor-custom-write]. Note that this is checked last, after all of the above cases.}
]
}

@defproc[(cbor-read [config cbor-config?]
                    [in input-port? (current-input-port)])
         any/c]{
Reads a binary-serialized CBOR value from @racket[in].
Major types are decoded as follows:
@itemlist[
@item{Major type 0 (unsigned integer) and 1 (negative integer) are decoded as standard Racket integers}
@item{Major type 2 (byte string) and 3 (string) are decoded as Racket @racket[bytes?] and @racket[string?], respectively}
@item{Major type 4 (list) is decoded as a Racket @racket[list?] of the contained values}
@item{Major type 5 (map) is decoded as a Racket @racket[hash-equal?] of the contained key-value pairs}
@item{Major type 6 (tag) is decoded according to the registered tag deserializers (see @racket[cbor-config]). If no deserializer is registered, the contents are stored in @racket[cbor-tag].}
@item{Major type 7, additional data 20, 21, and 23 (false, true, and undefined) are decoded as @racket[#f], @racket[#t], and @racket[undefined], respectively}
@item{Major type 7, additional data 22 is decoded as the value of @racket[(cbor-config-null-value config)]}
@item{Major type 7, additional data 25, 26, and 27 (half float, single float, and double float, respectively), are all decoded as Racket @racket[flonum?]. Note that this library decodes all of these three types to Racket's double-width floating point type.}
@item{Any other item with major type 7 and additional data matching @racket[cbor-unassigned-simple-value?] is decoded as a @racket[cbor-simple-value]}
]
}

@section{Configuration Options}
@defstruct[cbor-config ((tag-deserializers (hash/c cbor-valid-tag-number? (-> cbor-valid-tag-number? any/c any/c))) (null-value any/c))]{
Configuration object for CBOR encoding and decoding. Note that this struct is only exposed opaquely, and must be manipulated with the provided functions and values.

@racket[tag-deserializers] is a hash from CBOR tag numbers to a procedure that takes the CBOR tag number and a raw data value and produces the meaningful interpretation of that value.

@racket[null-value] is the value that CBOR @tt{null} will be encoded and decoded as.
}

@defthing[cbor-empty-config cbor-config?]{
Base configuration object, with no tag deserializers registered and null value set to @racket['null].
}

@defproc[(with-cbor-tag-deserializer [config cbor-config?]
                                     [id cbor-valid-tag-number?]
                                     [deserializer (-> cbor-valid-tag-number? any/c any/c)])
         cbor-config?]{
Registers a tag deserializer to the given config, returning a new config.
}

@defproc[(with-cbor-null-value [config cbor-config?]
                               [v any/c])
         cbor-config?]{
Registers a null value to the given config, returning a new config.
}

@defthing[gen:cbor-custom-write any/c]{
A @tech{generic interface} that supplies a method, @racket[cbor-write-proc] that can serialize arbitrary values to CBOR. Implementations of the method should accept a value to be serialized and return it in serialized form as a @racket[cbor-tag?].
}

@section{Auxiliary Items}

@defproc[(cbor-valid-tag-number? [v any/c])
         boolean?]{
Equivalent to @racket[(integer-in 0 18446744073709551616)].
}

@defproc[(cbor-unassigned-simple-value? [v any/c])
         boolean?]{
Equivalent to @racket[(or/c (integer-in 0 19) (integer-in 32 255))].
}

@defstruct[cbor-tag ([number cbor-valid-tag-number?] [content any/c])]{
Raw representation of a CBOR tag with tag number @racket[number] and tag content
@racket[content]. @racket[content] must be serializable by @racket[cbor-write].
}

@defstruct[cbor-simple-value ([inner cbor-unassigned-simple-value?])]{
Represents a CBOR Simple Value. Only simple values that have not been assigned a meaning via
RFC can be represented as this struct. Simple Values with predefined meaning such as @racket[#f] are always serialized and deserialized directly as their meaningful forms.
}

@section{Bugs}
Patches to improve these issues are welcome! Email patches to @tt{~williewillus/public-inbox (at) lists.sr.ht}.
@itemlist[
@item{Some functions are currently too lax (indefinite-length objects can be nested in nonconforming ways).}
@item{There should be a config or parameter to specify maximum lengths for indefinite-length objects}
@item{More correctness-testing is needed.}
@item{Some recommended tag and simple values from the RFC are not supported yet.}
]