Runtime helpers for ~NFT sigils that contain #{...}
interpolations.
When the sigil body has no interpolations, Linx.NFT.Compiler
produces a %Linx.Netfilter.Ruleset{} at compile time and the
macro emits it as a literal. When there are interpolations, the
static value isn't knowable until runtime, so
Linx.NFT.RuntimeCompiler emits Elixir code that constructs the
Ruleset at runtime. At each #{expr} position, it calls into
one of the helpers here — they take an evaluated Elixir value
plus the field kind the surrounding nft syntax expects
({:int, 1|2|4|8}, :ipv4, :ipv6, :ifname), validate, and
return either an encoded %Expr{} ready to splice into the
rule's expression list or the raw bytes to use as a comparison
value.
Errors at runtime raise ArgumentError with a message naming
the expected kind and the actual value — there's no
source-location context here (the macro keeps the AST node's
meta on the static side, but the runtime helper just sees the
value), so test the interpolated values close to the sigil
call site.
Supported value kinds
{:int, width}—width∈1, 2, 4, 8bytes, big-endian encoded. Accepts any non-negative integer that fits.:ipv4—Linx.IP.parse/1-able string, 4-tuple{a, b, c, d}, raw 4-byte binary, or%Linx.IP{family: :inet}. Returns 4 bytes.:ipv6— same shape extended: parse-able string, 8-tuple of0..0xFFFF, raw 16-byte binary, or%Linx.IP{family: :inet6}. Returns 16 bytes.:ifname— binary, padded/truncated to IFNAMSIZ (16 bytes) with trailing zero bytes.
Each kind has a matching encode_*!/1 helper that returns the
raw bytes, plus the convenience cmp!/3 that wraps the bytes
in an %Expr{name: :cmp} ready to splice into a rule.
Summary
Functions
Encodes value for the given kind, then builds an
%Expr{name: :cmp} with op. Returns the %Expr{}. Raises
ArgumentError if value doesn't match the expected kind.
Encodes value to a binary suitable for the given kind. Raises
ArgumentError on type mismatch / out-of-range.
Pads an interface-name binary out to IFNAMSIZ (16 bytes) with trailing zeros. Truncates if longer (matches kernel behaviour — the trailing bytes are ignored).
Encodes an integer to a width-byte big-endian binary.
Encodes an IPv4 input to its 4-byte big-endian form.
Encodes an IPv6 input to its 16-byte big-endian form.
Functions
@spec cmp!(atom(), term(), {:int, 1 | 2 | 4 | 8} | :ipv4 | :ipv6 | :ifname) :: Linx.Netfilter.Expr.t()
Encodes value for the given kind, then builds an
%Expr{name: :cmp} with op. Returns the %Expr{}. Raises
ArgumentError if value doesn't match the expected kind.
Encodes value to a binary suitable for the given kind. Raises
ArgumentError on type mismatch / out-of-range.
@spec encode_ifname!(binary()) :: <<_::128>>
Pads an interface-name binary out to IFNAMSIZ (16 bytes) with trailing zeros. Truncates if longer (matches kernel behaviour — the trailing bytes are ignored).
Encodes an integer to a width-byte big-endian binary.
@spec encode_ipv4!(term()) :: <<_::32>>
Encodes an IPv4 input to its 4-byte big-endian form.
@spec encode_ipv6!(term()) :: <<_::128>>
Encodes an IPv6 input to its 16-byte big-endian form.