if Code.ensure_loaded?(FSST.Table) do defmodule QuackDB.Protocol.FSST do @moduledoc """ Internal bridge to the optional `:fsst` package. DuckDB currently flattens FSST vectors before Quack serialization in the versions QuackDB targets. This module keeps the package boundary ready for future Quack payloads that expose serialized FSST symbols and compressed string payloads. """ alias QuackDB.Error @spec decompress_values([binary()], [binary()]) :: {:ok, [binary()]} | {:error, Error.t()} def decompress_values(symbols, payloads) when is_list(symbols) and is_list(payloads) do with {:ok, table} <- table_from_symbols(symbols) do decompress_payloads(table, payloads, []) end end def decompress_values(_symbols, _payloads) do error(:invalid_fsst_payload, "expected FSST symbols and payloads to be lists") end defp table_from_symbols(symbols) do case FSST.Table.from_symbols(symbols) do {:ok, table} -> {:ok, table} {:error, reason} -> error(:invalid_fsst_symbols, "invalid FSST symbol table: #{inspect(reason)}") end end defp decompress_payloads(_table, [], acc), do: {:ok, Enum.reverse(acc)} defp decompress_payloads(table, [payload | payloads], acc) when is_binary(payload) do case FSST.decompress(table, payload) do {:ok, value} -> decompress_payloads(table, payloads, [value | acc]) {:error, reason} -> error(:invalid_fsst_payload, "invalid FSST payload: #{inspect(reason)}") end end defp decompress_payloads(_table, [_payload | _payloads], _acc) do error(:invalid_fsst_payload, "expected compressed FSST payloads to be binaries") end defp error(code, message) do {:error, Error.new(code, message, source: :protocol)} end end end