Summary

  • RFC 1014 made XDR values occupy multiples of four bytes. A variable-length string travels with a four-byte count, its character bytes, and enough zero fill to reach the next four-byte boundary.
  • The RFC's worked example encodes sillyprog as count 9, nine character bytes, and three fill bytes. The following file-kind value starts at offset 16. The count identifies the name; the padding positions the next field.

There is a little joke hiding in the hex dump near the end of RFC 1014. A user called john wants to store a Lisp program named sillyprog. Sun's example gives the filename a four-byte length field, nine bytes of letters, and three bytes of silence. The name occupies twelve bytes after its count. At offset 16, the next value begins as neatly as a train arriving at a numbered platform. The zeros bought the timetable.

In 1987 a program could send data from a Sun workstation to a VAX, an IBM PC or a Cray. Those machines had their own habits for storing numbers and arranging memory. XDR, the External Data Representation standard Sun described for Internet consideration, supplied a common description and encoding for values crossing that divide. Sun RPC and NFS used it to describe their data. The memo's chosen unit was an eight-bit byte, and its recurring architectural rhythm was four bytes.

The rule sounds almost petty: every item occupies a multiple of four bytes. A 32-bit integer already fits. A shorter or uneven byte sequence receives up to three zeros at its end. In a stream of differently sized values, that regular rhythm gives a decoder a reliable place to look for the next item. The sender has to count accurately; the receiver has to advance over the data and its padding. The wire carries a few spare bytes so both machines can keep their place.

For a variable-length string, the first four bytes encode the number of characters. The characters follow. Then come zero bytes until the item ends on a four-byte boundary. The count describes the string's content; the zeros finish its container. In the sillyprog example, count 9 sits at offsets 0 through 3. The nine letters fill offsets 4 through 12. Three zeros take offsets 13 through 15. The file-kind value begins at offset 16, where the reader expects it. Treating the zeros as letters would change the name. Forgetting them would shift every field that followed.

The worked example does more than explain one filename. Its file-kind field is EXEC, encoded as 2. That choice selects an interpreter field containing lisp, with its own count 4 and four letters. The owner john gets the same counted-string treatment. Finally, the data (quit) consists of six bytes, preceded by count 6 and followed by two zeros. The structure repeats the rule without giving each field the same natural length. Every variable-length piece announces how much content it owns; padding restores the four-byte beat before the next piece starts.

Opaque data follows a similar counted shape, but its bytes are left uninterpreted. An XDR string in this memo is a sequence of ASCII bytes. Both can declare a maximum length, and encoding a longer sequence violates that declaration. This makes the count do two jobs: it guides the reader to the end of the value and gives the reader a length to check against the declared bound. The trailing zeros then put the next field in its expected place. Count, content, fill; the order is plain enough to audit with a pencil.

The distinction matters because a machine-to-machine exchange cannot rely on the layout of a local C object. A pointer in one process is useless to a different computer. A padding habit inside one compiler may differ from another. XDR's description language specified the data structure and the bytes that represented it. A receiver could walk the shared encoding instead of inheriting the sender's memory customs. The RFC even provided a discriminated union: a file kind could select which additional field followed. The file example uses that device to attach an interpreter to EXEC.

Three wasted bytes sound like a tiny tax, and they are. The alternative cost would be to lose the position of the next value. Sun's example makes the trade visible without a performance chart: nine bytes of filename occupy twelve payload bytes, and the following four-byte file kind starts at offset 16. A reader can verify the calculation at each boundary. The protocol did not ask the recipient to admire the zeros. It asked the recipient to step over them at the right moment.

A file named sillyprog is an unusually cheerful witness for a dry data format. Its name is short; the lesson is durable. In a stream shared by machines with different native habits, the empty seats can be part of the agreement that keeps the occupied ones legible.