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
Sebb
September 6, 2021, 8:55pm
2
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
Sebb
September 6, 2021, 9:01pm
4
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.
al2o3cr
September 6, 2021, 11:59pm
6
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