Equivalent way to perform Ruby string or number pack unpack in Elixir?

In ruby you can do something like “aa7ce”.pack(“C2S>”)

How would one accomplish the same in Elixir?

As far as I know (I might be wrong), there is no equivalent to pack/unpack in Elixir.

That being said, the most common thing to pack/unpack is to convert characters to their codepoints and vice-versa. This can be done in Elixir by simply converting a binary to a charlist, which is a list of codepoints.

If you want to change that to e.g. a 32-bit-sized int, you’ll have to do this manually, which is the easiest by using the bitshifting operators from Data.Bits.

I have no clue what ruby’s pack is (you really should include such information in your post ;-)), but if it is like python’s pack in the struct module then it is just binary combining/parsing, which is built into Elixir/Erlang itself via the <<blah>> syntax.

EDIT: Based on http://blog.bigbinary.com/2011/07/20/ruby-pack-unpack.html it does look like ruby’s pack/unpack is like pythons pack/unpack, which in that case Elixir/Erlang’s is significantly more powerful and easier to use. If you give example of what to parse ("C2S>" means nothing to me to be honest, but like what you actually want to parse in what binary format) then I can convert it for you to show. Erlang was built to be a network layer parsing and managing language after all. :slight_smile:

1 Like

Binary pattern matching tends to be wildly more useful than packing /unpacking in elixir.

Do you mean unpack for your example btw? pack is on the Array class not the string class. If we go with unpack, here’s the equivalent in elixir.

iex(2)> << int1 :: unsigned-8, int2 :: unsigned-8, int3 :: unsigned-big-16, _ :: bitstring>> = "aa7ce"
iex(3)> int1
iex(4)> int2
iex(5)> int3

To me this is 1000x clearer than the esoteric unpack syntax.


You are point on @benwilson512 . Precisely what I needed. Thanks.

@OvermindDL1 The precise API definition for packing/unpacking string containing binary data is what I’m looking for.


“C2S>” would be unsigned-8-bit-char Int (twice), unsigned-16-bit-big-endian Int.

@benwilson512 gave the precise feedback I needed.

Thank you.


Yes, it’s much clearer, but it’s not pipe-able.

For example, I want to calculate some integer, treat it as a 64-bit string, then base64 encode it, I have to write

x = 789
      |> Bitwise.<<<(16)
      |> Bitwise.|||(456)
      |> Bitwise.<<<(8)
      |> Bitwise.|||(123)

Base.encode64(<<x :: 64>>)

The last step is not pipe-able.

You could do something like:

|> Bitwise.<<<(16)
|> Bitwise.|||(456)
|> Bitwise.<<<(8)
|> Bitwise.|||(123)
|> (fn x -> <<x :: 64>> end).()
|> Base.encode64()