Next: XDR Standard Data Types, Previous: Implementation of XDR, Up: Implementation of XDR
The XDR standard defines various basic data types and allows for the definition of compound data types (“structs”), fixed-size and variable-size arrays as well as “unions”. Fixed-size arrays and structs can actually be thought as the same type: Their size if known in advance and they are encoded as the succession of the data they contain. Thus, those types can be summarized as 4 great classes: “basic” types, variable-length arrays, structs and unions.
The (rpc xdr) module provides facilities to create Scheme objects
representing XDR data types and to manipulate them. These Scheme
objects, described below, are all immutable, i.e., they cannot be
modified after creation.
This returns an
<xdr-basic-type>object describing a type whose encoding fits on size octets, and which is encoded/decoded using the encoder and decoder procedures. type-pred should be a predicate checking the validity of an input Scheme value for encoding into this type.Optionally, vector-encoder and vector-decoder can be passed and should be procedures that efficiently encode/decode sequences of data items of this type (for instance, the vector decoder could use the
bytevector->int-listprocedure of the(r6rs bytevector)module to speed up decoding). The vector encoder is invoked as(vector-encodertype value bv index)while the vector decoder is invoked as(vector-decodertype count port).Users should normally not need to define new basic types since all the basic types defined by XDR are already available in
(rpc xdr types)(see XDR Standard Data Types). Thus, we will not describe its use further.
Return a new XDR struct type made of a sequence of XDR data items whose types are listed in base-types.
Struct types encode from/decode to Scheme lists whose length is that of base-types.
Return an object describing an XDR variable-length array of elements of types base-type (again, an XDR type object). If max-element-count is a number, then it describes the maximum number of items of type base-type that are allow in actual arrays of this type. If base-type is
#f, then arrays of this type may contain up to 2^32 - 1 items of type base-type.Vector types are encoded from generalized vectors such as Scheme vectors, SRFI-4 vectors or strings (see Generalized Vectors). By default, vector types decode to vectors, but any other kind of generalized vector can be used: it only needs to be specified as the vector-decoder argument of
make-xdr-basic-typefor the corresponding base type. Of course, SRFI-4 vectors, for example, may only be used when an XDR integer vector with a matching integer range is expected.If max-element-count is specified and a vector to be encoded contains more than max-element-count elements, then an
&xdr-vector-size-exceeded-errorerror condition is raised. Likewise, if XDR data to be decoded describes vectors larger than max-element-count, this error condition is raised.
Return a new XDR discriminated union type, using discr-type as the discriminant type (which must be a 32-bit basic type) and discr/type-alist to select the “arm” type depending on the discriminant value. If no suitable value is found in discr/type-alist and default-type is not
#f, then default type is used as the arm type.Union types encode from/decode to Scheme pairs whose
caris the discriminant's value and whosecdris the actual union value.
Return the type that should be used for union's arm given discriminant (a Scheme value).
Sometimes, one may want to define recursive types, i.e., types that refer to themselves. This is particularly useful to implement lists. For example, in XDR language, a list of integers can be defined as follows:
struct integer_list_t
{
int x;
integer_list_t *next;
};
This notation is a shortcut for the following structure:
struct integer_list_t
{
int x;
union switch (bool opted)
{
case TRUE:
integer_list_t value;
case FALSE:
void;
} next;
};
The integer_list_t type references itself. Defining it using our
API seems impossible at first: one cannot pass a self-reference to
make-xdr-struct-type (since the object is not yet created!), and
the self-reference cannot be added after the fact since objects returned
by make-xdr-struct-type are immutable.
The API addresses this problem by allowing thunks (zero-argument
procedures) to be used as types. Together with Scheme's letrec
recursive binding construct or a top-level define (see letrec), it makes it possible to create such
recursive types:
(letrec ((integer-list
(make-xdr-struct-type
(list xdr-integer
(make-xdr-union-type xdr-boolean
`((TRUE . ,(lambda ()
integer-list))
(FALSE . ,xdr-void))
#f)))))
integer-list)
The trick here is that using the thunk effectively defers the evaluation of the self-reference1.
It is often useful to know the size in octets it takes to encode a given value according to an XDR type. However, as we just saw, the size of some XDR types (variable-length arrays and unions) cannot be known in advance: The encoding size depends on the actual value to encode. The following procedure allow the computation of the size of the XDR representation of some value.
Return the size (in octets) of type when applied to value. type must be an XDR type object returned by one of the above procedures, while value should be a Scheme value suitable for encoding with type.
The following section lists the standard XDR data types.
[1] This idea was inspired by Oleg Kiselyov's description of thunked parent pointers in SXML, which may be found at http://okmij.org/ftp/Scheme/parent-pointers.txt.