How to pad a binary with 0's?

Hi all,

I’m trying to write out a string, in binary, using Elixir’s <<>> syntax, and am having a dumb moment. I have a requirement where if a template name string isn’t 16 characters long then the remaining bytes must be padded with zeros.

Here is the header I’m trying to write:

┌──────────────────┬───────────┬────────────────┬──────────────────┬───────────┬───────────┐
│       TAG        │ Label Len │ Content Length │   Template Name  │  Contents │ Signature │
├──────────────────┼───────────┼────────────────┼──────────────────┼───────────┼───────────┤
│4x Unsigned Chars │    u16    │      u64       │  16byte char str │           │           │
└──────────────────┴───────────┴────────────────┴──────────────────┴───────────┴───────────┘

What I have so far is:

label_bin =
      <<"TAG1", label_metadata.label_len::16, label_metadata.content_length::64>>

I’m not sure how to write the Template name in the same way as above. Do I need to create another IO structure and just append the 0’s?

Thanks,
Jeramy

template_name = "foo"
pad = 16 - byte_size(template_name)
<<template_name::binary, 0::pad*8>>

Edit: Note that this may crash: How to pad a binary with 0's? - #6 by al2o3cr

5 Likes

Awesome, that worked like a charm! Would you mind pointing me to some documentation on this? A quick search isn’t finding anything

here: Kernel.SpecialForms — Elixir v1.12.3

also useful: Erlang -- binary
(but there is nothing there that helps you with this, would be nice).

Don’t use String for this.

2 Likes

Oh, turns out to be a huge fail on my part. It didn’t occur to me to just write 0s over the amount of bytes left like your example above.

The given solution will crash if template_name is longer than 16 characters; this may be fine, depending on where the name is coming from etc.

If crashing isn’t acceptable, than the string will need to be truncated. You can do both the padding and the truncating together with a little pattern matching:

<<padded_and_trimmed::bits-size(128), _::bits>> = <<template_name::binary, 0::128>>

This works by initially padding template_name with 16 bytes of zeros, then taking only the first 16 bytes of the remainder.

The truncation can also be done as part of a larger step, like your label_bin:

padded_name = <<template_name::binary, 0::128>>
label_bin =
      <<"TAG1", label_metadata.label_len::16, label_metadata.content_length::64, padded_name::bits-size(128), ...>>
2 Likes