Next: XDR Standard Data Types, Previous: Implementation of XDR, Up: Implementation of XDR [Contents][Index]
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-list
procedure of the (rnrs bytevectors)
module to speed up decoding). The vector encoder is invoked as
(vector-encoder type value bv index)
while the vector
decoder is invoked as (vector-decoder type 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 arrays, which includes Scheme
vectors, SRFI-4 vectors or strings (see Arrays in The GNU Guile Reference Manual). By default, vector types decode to
vectors, but any other kind of array can be used: it only
needs to be specified as the vector-decoder argument of
make-xdr-basic-type
for 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-error
error 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 car
is the
discriminant’s value and whose cdr
is 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
in Revised^5 Report on the
Algorithmic Language Scheme), 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-reference2.
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.
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.
Next: XDR Standard Data Types, Previous: Implementation of XDR, Up: Implementation of XDR [Contents][Index]