# Selectively unpacking binary data

**URL:** https://discourse.julialang.org/t/selectively-unpacking-binary-data/64768
**Category:** General Usage
**Tags:** binaryio
**Created:** [July 16, 2021, 7:10pm UTC](https://discourse.julialang.org/t/selectively-unpacking-binary-data/64768 "2021-07-16T19:10:56Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![Mikhail\_Kagalenko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikhail_kagalenko/32/13257_2.png) [@Mikhail\_Kagalenko](https://discourse.julialang.org/u/Mikhail_Kagalenko)
#### Post date: [July 16, 2021, 7:10pm UTC](https://discourse.julialang.org/t/selectively-unpacking-binary-data/64768/1 "2021-07-16T19:10:57Z")

</div>

I need to unpack a few values of known types and offsets from a binary file. The difference with earlier discussed cases is, firstly, that the values are not adjacent in the file, so it is necessary to specify offsefs; secondly, there are some differences in the way the values are packed. So I may do something like this:

```julia
struct Foo
  val1:: Int32
  val2::Float16
  val3::UInt64
end
foo_layout=[12 :pack_style_1; 34 :pack_style_2; 56 pack_style_3]

```

Then the unpacking function itrates over fields of Foo, reads them into `v::Vector{Any} `, taking into account the offsets and styles, and then returns `Foo(v...)`. The drawback of this solution is the necessity to keep in sync the separate definitions of Foo and its layout. It would be more convenient to supply some “pragmas” within the definion of Foo, and then having a macro to generate both the struct and the layout description:

```julia
@gen_layout struct Foo
  val1:: Int32 # 12 :pack_style_1
  val2::Float16 # 34 :pack_style_2
  val3::UInt64 # 56 :pack_style_3
end

```

What is unclear to me is, if the metaprogramming facilities work on the parsed AST, do they have access to the comments?

Or maybe, there’s some altogether better way to do this?

---

<div class="post-metadata">

### Author: ![Mikhail\_Kagalenko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikhail_kagalenko/32/13257_2.png) [@Mikhail\_Kagalenko](https://discourse.julialang.org/u/Mikhail_Kagalenko)
#### Post date: [July 25, 2021, 11:08am UTC](https://discourse.julialang.org/t/selectively-unpacking-binary-data/64768/2 "2021-07-25T11:08:57Z")

</div>

Somewhat better way to define the layout would be with traits:

```julia
struct Foo
  val1:: Int32
  val2::Float16
  val3::UInt64
end
layout(::Type{Foo})=[12 :pack_style_1; 34 :pack_style_2; 56 pack_style_3]

for T in [Foo, Bar, Baz]
    @assert fieldcount(T) == size(layout(T), 1)
end

```

In that case, it becomes unnecessary to export the layout definition and parsing function may look like this

```julia
function parse_struct(io::IOStream, ::Type{T})
  t_layout = layout(T)
  K = fieldcount(T)
  vars = Vector{Any}(undef, K)
  for k in 1:K
    seek(io, t_layout[k, 1])
    vars[k] = read_value(io, fieldtype(T, k), t_layout[k, 2])
  end

  return T(vars...)
end

```
