Featured image

One of the coolest and most thoughtfully implemented features in Ruby is data packing and unpacking. I haven’t encountered such a simple API for working with binary data even in compiled languages like Go, Rust, or C++.

For example, if you need to turn two bytes into a 16-bit integer, it looks like this:

[32, 255].pack('C*').unpack('S>')
=> [8447]

To make it clearer what’s happening, let’s add 1 byte to the result and unpack it back into an array of bytes:

[8447 + 256].pack('S>').unpack('C*')
=> [33, 255]

You can also easily convert bytes into a hexadecimal or binary string:

[32, 255].pack('C*').unpack('H*').first.chars.each_slice(2).map(&:join)
=> ["20", "ff"]

[33, 255].pack('C*').unpack('B*').first.chars.each_slice(8).map(&:join)
=> ["00100001", "11111111"]

And this is just a fraction of all possible use cases.

Have you ever used Array#pack and String#unpack in your projects?