NFTables.Decoder (NFTables v0.8.2)
View SourceUniversal decoder for all nftables responses.
Handles read operations, write operations, mixed operations, and errors.
Architecture
The Decoder sits between NFTables.Local and user code, transforming nftables JSON responses into idiomatic Elixir structures:
Query.list_tables() # Build command (pure function)
|> NFTables.Local.submit(pid: pid) # Execute & JSON decode
|> Decoder.decode() # Transform to ElixirResponse Types
Write-Only Responses
Empty responses from write operations (add, delete, flush):
:okRead-Only Responses
Data responses from list operations, flat structure matching nftables:
{:ok, %{
tables: [%{name: "filter", family: :inet, ...}],
chains: [%{name: "INPUT", table: "filter", ...}],
rules: [%{handle: 5, table: "filter", chain: "INPUT", ...}],
sets: [%{name: "blocklist", table: "filter", ...}]
}}Empty lists are filtered out automatically.
Mixed Responses
Operations with both writes and reads:
{:ok, %{
operations: [:success, :success],
data: %{tables: [...], chains: [...]}
}}Error Responses
Contextual errors indicating operation type:
{:error, {:write_failed, reason}}
{:error, {:read_failed, reason}}
{:error, {:mixed_failed, reason}}Examples
# Write operation
Builder.new()
|> NFTables.add(table: "filter", family: :inet)
|> NFTables.submit(pid: pid)
#=> :ok
# Read operation
Query.list_tables(family: :inet)
|> NFTables.Local.submit(pid: pid)
|> Decoder.decode()
#=> {:ok, %{tables: [...]}}
Summary
Functions
Universal decode function that handles any nftables response.
Types
@type decoded_response() :: :ok | {:ok, decoded_data()} | {:ok, %{operations: [:success], data: decoded_data()}} | {:error, {atom(), term()}}
Functions
@spec decode({:ok, map()} | {:error, term()}) :: decoded_response()
Universal decode function that handles any nftables response.
Automatically detects response type (write/read/mixed/error) and transforms to appropriate Elixir structure.
Parameters
response- The response tuple from NFTables.Local.submit/2
Returns
:ok- For successful write-only operations{:ok, %{...}}- For read-only operations with data{:ok, %{operations: [...], data: %{...}}}- For mixed operations{:error, {context, reason}}- For errors with context
Examples
# Write-only (empty response)
Decoder.decode({:ok, %{}})
#=> :ok
# Read-only (has data)
Decoder.decode({:ok, %{"nftables" => [%{"table" => ...}]}})
#=> {:ok, %{tables: [...]}}
# Mixed (batch with writes and reads)
Decoder.decode({:ok, %{"nftables" => [empty, %{"table" => ...}]}})
#=> {:ok, %{operations: [:success], data: %{tables: [...]}}}
# Error
Decoder.decode({:error, "Table already exists"})
#=> {:error, {:write_failed, "Table already exists"}}