pack: Binary encoding and decoding

This module provides low-level facilities for converting Alore objects to and from packed binary representations (this is called packing and unpacking, respectively). The packed representations are narrow strings that can written to files, sockets and other narrow streams. Strings containing character codes larger than 255 (wide strings) must be encoded before passing them to the packing methods (using the encodings module, for example).

This module is typically used for accessing and generating binary data using standard binary formats, for implementing binary network protocols and interoperating with lower-level languages such as C.

Pack formats

Binary data can be packed in several different formats. Some formats can only pack integer data, others floating point numbers, and finally there is a format for string data. There are no separate formats for different endiannesses — instead there are separate classes for packing and unpacking big endian and little endian data.

The table below contains descriptions of the supported formats, including sizes of the packed representations and the corresponding Alore types that can be packed into and unpacked from using each format (note that N in a format name must be replaced by a valid integer):

Format Description Packed bits Packed bytes Alore type
Byte unsigned byte1 8 1 Int
WordN unsigned integer N (16, 32 or 64) 2, 4, or 8 Int
IntN signed integer2 N (8, 16, 32 or 64) 1, 2, 4 or 8 Int
FloatN floating point number3 N (32 or 64) 4 or 8 Float
Str narrow string variable4 variable4 Str

Notes:

 1   The Byte format is thus named for convenience; for consistency's sake it could equivalently have been named Word8.
 2   Signed integer formats (Int8 to Int64) are encoded using the standard 2's complement encoding.
 3   The Float32 and Float64 formats correspond to single and double precision IEEE floating point numbers, respectively.
 4   The width of a Str format is always specified with an additional integer argument specifying the length of the packed string in bytes. When packing, input strings may be smaller than the length; they will be padded with spaces so that the desired length is reached.

Packer classes

There are two packer classes, one for the big-endian (network) byte order and other for the little-endian byte order. They both support the same methods.

class Packer()
Construct a packer that packs and unpacks data in the big-endian (network) byte order.
class LittleEndianPacker()
Construct a packer that packs and unpacks data in the little-endian byte order.

Methods

Note: Instances of N in method names below must be replaced with an integer valid for the format. See the above table for details. For example, the actual methods for packing words are packWord16, packWord32 and packWord64.

packByte(int)
packWordN(int)
packIntN(int)
packFloatN(float)
packStr(str, len)
Pack a value in a specific format. The argument must have a compatible Alore type for the format (integers are also valid when floats are expected). The result is a narrow string.
packBytes(array)
packWordsN(array)
packIntsN(array)
packFloatsN(array)
packStrs(array, len)
Pack an array of values in a specific format. The argument must be an array, and each array item must have a compatible Alore type for the format. The result is a narrow string that is the concatenation of the packed items.
unpackByte(str)
unpackWordN(str)
unpackIntN(str)
unpackFloatN(str)
unpackStr(str)
Unpack a narrow string encoded in the format specified by the method name. The argument must have the correct length for the format. The Alore type of the result value is specified by the format.
unpackBytes(array)
unpackWordsN(array)
unpackIntsN(array)
unpackFloatsN(array)
unpackStrs(array, len)
Unpack a narrow string that contains any number of values encoded in the format specified by the method name. The argument must have a valid length for the format (any multiple of the single item length). The result is an array of values whose type is specified by the format.

Examples

var p = Packer()
p.packWord16(7)               -- Result: "\u0000\u0007"
p.packBytes([16, 128])        -- Result: "\u0010\u0080"
p.unpackBytes("\u0010\u0080") -- Result: [16, 128]

var pl = LittleEndianPacker()
pl.packWord16(7)              -- Result: "\u0007\u0000"

The PackStream class

class PackStream(stream[, packer][, bufMode])
Construct a PackStream instance that uses another stream for input/output. Inherits from Stream. The packer argument, if present, must be a packer object. If omitted, the big endian packer will be used. The bufMode argument may be Buffered, LineBuffered or Unbuffered. If omitted, full buffering will be used.

PackStream methods

Note: Instances of N in method names below must be replaced with an integer valid for the format. See the above table for details. For example, the actual methods for writing words are writeWord16, writeWord32 and writeWord64.

writeByte(int)
writeWordN(int)
writeIntN(int)
writeFloatN(float)
writeStr(str, int)
Pack data and write to the stream. The arguments are similar to the corresponding pack* methods (see above).
writeBytes(array)
writeWordsN(array)
writeIntsN(array)
writeFloatsN(array)
writeStrs(array, int)
Pack an array and write to the stream. The arguments are similar to the corresponding pack* methods (see above).
readByte()
readWordN()
readIntN()
readFloatN()
Read and unpack data from the stream. The format specifies the number of characters (bytes) to read and the type of the return value.
readBytes(n)
readWordsN(n)
readIntsN(n)
readFloatsN(n)
readStrs(n, len)
Read and unpack multiple data items from the stream. The format and the length argument specify the number of characters (bytes) to read and the length of the Array return value and the type of its items.
eof()
seek(n)
close()
Call the corresponding method of the underlying stream (if it is supported).

The inherited writing and reading methods (write, readLn, etc.) behave normally and can be used in addition to the PackStream specific input/output methods.

The PackFile class

class PackFile(path[, packer], ...)
Open a binary file for reading and/or writing. The supported additional arguments are the same as for io::File. The packer argument, if present, must be a packer object (see above). If omitted, the big endian packer will be used.

PackFile inherits from PackStream.

Example:

var f = PackFile("file.bin", Output)
f.writeWord32(1234)
f.writeBytes([1, 2, 3, 4])
f.close()

Constants

HostByteOrderPacker
This constant refers to either Packer or LittleEndianPacker depending on the native byte order of the host system.

Exceptions

class PackError
Raised when a packer class gets invalid input and cannot perform packing or unpacking. Inherits from std::ValueError.