Pack
Crystal port of Perl / Ruby's pack / unpack functions.
The basic usage is Pack.pack_to for writing to an IO, and Pack.unpack
for reading from a Bytes. The function Pack.pack writes to a new Bytes
and returns it.
require "pack"
Pack.unpack Bytes[0x01, 0xC8, 0x03, 0x04], "cCs" # => {1_i8, 200_u8, 1027_i16}
Pack.pack "csl>", 42_i8, -1000_i16, 1 << 31 # => Bytes[42, 24, 252, 128, 0, 0, 0]
The format string consists of any number of commands, which consist of a
directive (usually indicating the type of value to be read or written),
optionally followed by an integer count or a glob (*). Whitespaces between
commands are ignored, but must not appear in the middle of a command. The
directives are classified as below:
- Fixed-size integers (
cCsSlLqQnNvV) - Native integers (
iIjJ) - Floating-point values (
dfFeEgG) - BER-compressed integers (
w) - Binary strings (
aAZ) - UTF-8 characters / strings (
UU*) - Bitstrings and hexstrings (
bBhH) - Raw pointers and slices (
pP) - UU-encoded strings (
u) - Base64-encoded strings (
mM)
Fixed-size integers
These directives pack and unpack values of type T, where T <
Int::Primitive. The type T depends on the directive being used:
Int8:cUInt8:CInt16:sUInt16:SInt32:lUInt32:LInt64:qUInt64:Q
Due to auto-casting, compatible integer literals are allowed during packing:
Pack.pack("cs", 1, 1) # => Bytes[1, 1, 0]
These directives obey the system endianness, unless an endianness modifier is
supplied. < and > force the command to use little-endian and big-endian
respectively. The two modifiers cannot be specified in the same command.
The _ or ! modifier forces the command to use native-size integers
instead. See Native integers for the corresponding integer
types used.
The following aliases are defined:
nis equivalent toS>(stands for network byte order)Nis equivalent toL>vis equivalent toS<(stands for VAX byte order)Vis equivalent toL<
Endianness and native-size modifiers are not allowed after c, C, n, N,
v, and V.
Repeat counts are supported. Unpacking produces values of type
StaticArray(T, N), where N is the count specified in the command. Packing
accepts any Enumerable that is a collection of the appropriate element type.
If the value does not contain as many elements as specified, IndexError is
raised.
Globs are supported. Unpacking produces values of type Array(T). Packing
accepts any Enumerable that is a collection of the appropriate element type.
Native integers
These directives pack and unpack values of type T, where T <
Int::Primitive. The type T depends on the directive being used:
LibC::Short:s!LibC::UShort:S!LibC::Int:ii!LibC::UInt:II!LibC::Long:l!LibC::ULong:L!LibC::LongLong:q!LibC::ULongLong:Q!LibC::Int64T:jj!(stands for C'sintptr_t)LibC::UInt64T:JJ!(stands for C'suintptr_t)
Endianness modifiers are allowed on all of them, and have the same effect as fixed-size integers.
Native-size modifiers are allowed on all of them, including i, I, j, and
J for completeness.
Repeat counts and globs are supported in the same way as fixed-size integers.
Floating-point values
These directives pack and unpack values of type T, where T <
Float::Primitive. The type T depends on the directive being used:
Float32:fegFloat64:dEGLibC::Float32:F
The endianness also depends on the directive:
- System endian:
dfF - Little-endian:
eE - Big-endian:
gG
The D directive represents a native double-precision value in Ruby but a
long double value in Perl. To avoid confusion, this library does not support
D, because Crystal doesn't support long doubles.
Endianness and native-size modifiers are not allowed.
Repeat counts and globs are supported in the same way as fixed-size integers.
Constants
Macros
Packs args into a new writable Bytes according to the given format
string fmt.
Commands that contain repeat counts or globs do not consume multiple arguments.
fmt must be a string literal or string constant representing a valid sequence of unpacking commands. The arity and types of args depend on the commands given.
Pack.pack("csl>", 1_i8, 1000, 100000000) # => Bytes[0x01, 0xE8, 0x03, 0x05, 0xF5, 0xE1, 0x00]
Packs args into the given io according to the given format string fmt. The return value is unspecified.
Commands that contain repeat counts or globs do not consume multiple arguments.
io must be an IO. fmt must be a string literal or string constant
representing a valid sequence of unpacking commands. The arity and types of
args depend on the commands given.
io = IO::Memory.new
Pack.pack_to(io, "csl>", 1_i8, 1000, 100000000)
io.to_slice # => Bytes[0x01, 0xE8, 0x03, 0x05, 0xF5, 0xE1, 0x00]
Unpacks a buffer of bytes according to the given format string fmt.
Returns a Tuple of unpacked values, without flattening commands that
contain repeat counts or globs.
bytes must be a Bytes. fmt must be a string literal or string constant
representing a valid sequence of unpacking commands.
Pack.unpack(Bytes[0x01, 0xE8, 0x03, 0x05, 0xF5, 0xE1, 0x00], "csl>") # => {1_i8, 1000_i16, 100000000}
Pack.unpack("abcd\x00ef\x00".to_slice, "CCZ*a*") # => {StaticArray[97_u8, 98_u8], Bytes[99, 100], Bytes[101, 102, 0]}