M common.rkt => common.rkt +10 -2
@@ 31,9 31,11 @@
(provide cbor-config?
cbor-config-tag-deserializers
cbor-config-null-value
+ cbor-config-sorted-map-keys
(contract-out
[cbor-empty-config cbor-config?]
[with-cbor-null (-> cbor-config? any/c cbor-config?)]
+ [with-sorted-map-keys (-> cbor-config? boolean? cbor-config?)]
[with-cbor-tag-deserializer (-> cbor-config?
cbor-valid-tag-number?
(-> cbor-valid-tag-number? any/c any/c)
@@ 41,9 43,10 @@
(struct cbor-config
(tag-deserializers
- null-value))
+ null-value
+ sorted-map-keys))
-(define cbor-empty-config (cbor-config #hasheqv() 'null))
+(define cbor-empty-config (cbor-config #hasheqv() 'null #f))
(define (with-cbor-tag-deserializer config id deser)
(define old-handlers (cbor-config-tag-deserializers config))
@@ 55,3 58,8 @@
(struct-copy
cbor-config config
[null-value v]))
+
+(define (with-sorted-map-keys config sorted)
+ (struct-copy
+ cbor-config config
+ [sorted-map-keys sorted]))
M encode.rkt => encode.rkt +7 -3
@@ 93,9 93,13 @@
(define (cbor-write-map config m out)
(define len (hash-count m))
(write-argument out 5 len)
- (hash-for-each m (lambda (k v)
- (cbor-write config k out)
- (cbor-write config v out)))
+ (if (cbor-config-sorted-map-keys config)
+ (for-each (lambda (pair)
+ (cbor-write config (car pair) out)
+ (cbor-write config (cdr pair) out)) (sort (hash->list m) < #:key car))
+ (hash-for-each m (lambda (k v)
+ (cbor-write config k out)
+ (cbor-write config v out))))
(when (> len u64-max)
(write-break out)))
M info.rkt => info.rkt +1 -1
@@ 1,6 1,6 @@
#lang info
(define collection "cbor")
-(define version "0.9")
+(define version "0.10")
(define deps '("base"))
(define build-deps '("racket-doc"
"rackunit-lib"
M scribblings/manual.scrbl => scribblings/manual.scrbl +10 -2
@@ 55,12 55,14 @@ Major types are decoded as follows:
}
@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))]{
+@defstruct[cbor-config ((tag-deserializers (hash/c cbor-valid-tag-number? (-> cbor-valid-tag-number? any/c any/c))) (null-value any/c) (sorted-map-keys boolean?))]{
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.
+
+@racket[sorted-map-keys] determines whether or not map keys should be serialized in sorted order. This only affects encoding; unsorted map keys will still be decoded identically.
}
@defthing[cbor-empty-config cbor-config?]{
@@ 80,6 82,12 @@ Registers a tag deserializer to the given config, returning a new config.
Registers a null value to the given config, returning a new config.
}
+@defproc[(with-sorted-map-keys [config cbor-config?]
+ [v boolean?])
+ cbor-config?]{
+Set whether map keys should be serialized in sorted order.
+}
+
@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?].
}
@@ 113,4 121,4 @@ Patches to improve these issues are welcome! Email patches to @tt{~williewillus/
@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.}
-]>
\ No newline at end of file
+]