# `Linx.Netlink.Codec`
[🔗](https://github.com/oshlabs/linx/blob/v0.2.0/lib/linx/netlink/codec.ex#L1)

A small DSL for defining netlink message codecs.

Every netlink message body has the same shape — a fixed C-struct header
followed by a stream of type-length-value attributes. A module that `use`s
this one *declares* that shape in a `codec` block, and gets a struct plus an
`encode/1` and a `decode/1` generated for it:

    defmodule MyMessage do
      use Linx.Netlink.Codec

      codec do
        header do
          field :family, :u8
          pad 1
          field :index, :s32
        end

        attr 1, :name, :string
        attr 2, :mtu, :u32
      end

      # hand-written verbs may follow — the struct is already defined
    end

`encode/1` turns a `%MyMessage{}` into a message body; `decode/1` turns a
body back into a struct. Header fields default to `0`; an attribute field is
`nil` when absent, and a `nil` field is omitted on encode.

The whole definition is one `codec` block so the struct is defined right
there, before any hand-written functions below it can refer to it.

This module is the reference codec backend: the generated `encode/1` and
`decode/1` are thin wrappers over one shared engine driven by the declared
schema. The schema is also exposed as data through the generated
`__codec__/0` — the seam a future kernel-YAML-driven front end would target.

## Field and attribute types

Scalars `:u8`, `:u16`, `:u32`, `:u64`, `:s8`, `:s16`, `:s32`; `:string` (a
NUL-terminated string); `:binary` (raw bytes).

## The escape hatches

An attribute's type may also be:

  * a **module** that exports `encode/1` and `decode/1`. Pointed at another
    `Linx.Netlink.Codec` module it covers a nested attribute set; pointed at
    a hand-written module it covers any value whose wire form a primitive
    cannot express.
  * a **dispatch table**:
    `{:dispatch, :other_field, %{"k1" => Mod1, "k2" => Mod2, …}}`. The
    sub-codec is chosen at encode and decode time from the *current* value
    of `:other_field` — a sibling attribute on the same struct. The
    dispatching field must be declared *before* the dispatched one, so its
    value is in hand by the time the latter is processed.

Both let the DSL handle the regular case and step aside, to module-level
code, for the rest.

# `codec`
*macro* 

Declares a message codec: a `header` block of `field/2` and `pad/1` calls,
and `attr/3` declarations. Generates the struct, `encode/1` and `decode/1`.

A codec with no `header` block is a bare attribute set — the shape a nested
attribute takes.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
