serialize.ss: Serializing Data

To load: (require (lib "serialize.ss"))

(define-serializable-struct id (field-id ···) [inspector-expr])      SYNTAX

(define-serializable-struct (id super-id) (field-id ···) [inspector-expr])      SYNTAX

Like define-struct, but instances of the structure type are serializable with serialize. This form is allowed only at the top level or in a module's top level (so that deserialization information can be found later).

In addition to the bindings generated by define-struct, define-serializable-struct binds deserialize-info:id-v0 to deserialization information. Furthermore, in a module context, it automatically provides this binding.

Naturally, define-serializable-struct enables the construction of structure instances from places where make-id is not accessible, since deserialization must construct instances. Furthermore, define-serializable-struct provides limited access to field mutation, but only for instances generated through the deserialization information bound to deserialize-info:id-v0. See make-deserialize-info for more information.

The -v0 suffix on the deserialization enables future versioning on the structure type through define-serializable-struct/version.

When super-id is supplied, compile-time information bound to super-id must include all of the supertype's field accessors. If any field mutator is missing, the structure type will be treated as immutable for the purposes of marshaling (so cycles involving only instances of the structure type cannot be handled by the deserializer).

Example:

(define-serializable-struct point (x y))
(deserialize (serialize (make-point 1 2))) ; => (make-point 1 2)

(define-serializable-struct/version id vers-num (field-id ···) ((other-vers-num make-proc-expr cycle-make-proc-expr)) [inspector-expr])      SYNTAX

(define-serializable-struct/version (id super-id) vers-num (field-id ···) ((other-vers-num make-proc-expr cycle-make-proc-expr)) [inspector-expr])      SYNTAX

Like define-serializable-struct, but the generated deserializer binding is deserialize-info:id-vers-num. In addition, deserialize-info:id-other-vers-num is bound for each other-vers-num.

Each make-proc-expr should produce a procedure, and the procedure should accept as many argument as fields in the corresponding version of the structure type, and it produce an instance of id. Each graph-make-proc-expr should produce a procedure of no arguments; this procedure should return two values: an instance x of id (typically with #f for all fields) and a procedure that accepts another instance of id and copies its field values into x.

Example:

(define-serializable-struct point (x y))
(define ps (serialize (make-point 1 2)))
(deserialize ps) ; => (make-point 1 2)

(define x (make-point 1 10))
(set-point-x! x x)
(define xs (serialize x))
(deserialize xs) ; => x0, where x0 is (make-point x0 10)

(define-serializable-struct/versions point 1 (x y z)
                                     ([0 
                                       ;; Constructor for simple v0 instances:
                                       (lambda (x y) (make-point x y 0))
                                       ;; Constructor for v0 instance in a cycle:
                                       (lambda ()
                                         (let ([p0 (make-point #f #f 0)])
                                          (values
                                            p0
                                            (lambda (p)
                                              (set-point-x! p0 (point-x p))
                                              (set-point-y! p0 (point-y p))))))]))
(deserialize (serialize (make-point 4 5 6))) ; => (make-point 4 5 6)
(deserialize ps) ; => (make-point 1 2 0)
(deserialize xs) ; => x1, where x1 is (make-point x1 10 0)

(serialize v)      PROCEDURE

Returns a value that encapsulates the value v. This value includes only readable values, so it can be written to a stream with write, later read from a stream using read, and then converted to a value like the original using deserialize. Serialization followed by deserialization produces a value with the same graph structure and mutability as the original value, but the serialized value is a plain tree (i.e., no sharing).

The following kinds of values are serializable:

Of course, serialization succeeds for a compound value, such as a pair, only if all content of the value is serializable. If a value given to serialize is not completely serializable, the exn:fail:contract exception is raised.

See deserialize for information on the format of serialized data.

(deserialize v)      PROCEDURE

Given a value v that was produced by serialize, produces a value like the one given to serialize, including the same graph structure and mutability.

A serialized representation v is a list of six elements:

The result of deserialize shares no mutable values with the argument to deserialize.

If a value provided to serialize is a simple tree (i.e., no sharing), then the fourth and fifth elements in the serialized representation will be empty.

(make-deserialize-info make-proc cycle-make-proc)      PROCEDURE

Produces a deserialization information record to be used by deserialize. This information is normally tied to a particular structure because the structure has a prop:serializable property value that points to a top-level variable or module-exported variable that is bound to deserialization information.

The make-proc procedure should accept as many argument as the structure's serializer put into a vector; normally, this is the number of fields in the structure. It should return an instance of the structure.

The cycle-make-proc procedure should accept no arguments, and it should return two values: a structure instance x (with dummy field values) and an update procedure. The update procedure takes another structure instance generated by the make-proc, and it transfers the field values of this instance into x.

prop:serializable      PROPERTY

This property identifies structures and structure types that are serializable. The property value should be constructed with make-serialize-info.

(make-serialize-info to-vector-proc deserialize-id can-cycle? dir-path)      PROCEDURE

Produces a value to be associated with a structure type through the prop:serializable property. This value is used by serialize.

The to-vector-proc procedure should accept a structure instance and produce a vector for the instance's content.

The deserialize-id value indicates a binding for deserialize information, to either a module export or a top-level definition. The deserialize-id value can be an identifier syntax object, a symbol, or a pair:

See make-deserialize-info and deserialize for more information.

The can-cycle? argument should be false if instances should not be serialized in such a way that deserialization requires creating a structure instance with dummy field values and then updating the instance later.

The dir-path argument should be a directory path that is used to resolve a module reference for the binding of deserialize-id. This directory path is used as a last resort when deserialize-id indicates a module that was loaded through a relative path with respect to the top level. Usually, it should be (or (current-load-relative-directory) (current-directory)).

(serializable? v)      PROCEDURE

Returns #t if v appears to be serializable, without checking the content of compound values, and #f otherwise. See serialize for an enumeration of serializable values.