defmodule NLdoc.Stream.Message.Header do @moduledoc """ Stream Consumer """ @type numeric_header :: {String.t(), :long, integer()} @type string_header :: {String.t(), :longstr, String.t()} @type t :: numeric_header() | string_header() @doc """ Finds the header tuple in the given list matching the specified name and type. Returns the matching header tuple or `nil` if not found. ## Examples iex> headers = [ ...> {"x-stream-offset", :long, 42}, ...> {"x-stream-filter-value", :longstr, "uuid"} ...> ] iex> NLdoc.Stream.Message.Header.find(headers, "x-stream-offset", :long) {"x-stream-offset", :long, 42} iex> NLdoc.Stream.Message.Header.find(headers, "x-stream-filter-value", :longstr) {"x-stream-filter-value", :longstr, "uuid"} iex> NLdoc.Stream.Message.Header.find(headers, "x-stream-filter-value", :long) nil iex> NLdoc.Stream.Message.Header.find(headers, "non-existent", :long) nil """ @spec find(headers :: [t()], name :: String.t(), type :: :long) :: numeric_header() | nil @spec find(headers :: [t()], name :: String.t(), type :: :longstr) :: string_header() | nil def find(headers, name, type), do: headers |> Enum.find(fn {^name, :longstr, v} when type == :longstr and is_binary(v) -> true {^name, :long, v} when type == :long and is_integer(v) -> true _ -> false end) @doc """ Extracts the value from a header tuple. Returns the header's value if the header is present, or `nil` if the header is `nil`. ## Examples iex> NLdoc.Stream.Message.Header.value({"x-stream-offset", :long, 42}) 42 iex> NLdoc.Stream.Message.Header.value(nil) nil """ @spec value(header :: numeric_header()) :: integer() @spec value(header :: string_header()) :: String.t() @spec value(header :: nil) :: nil def value({_, _, value}), do: value def value(nil), do: nil @doc """ Searches for a header by name and type and returns its value. Returns the value for the header if found, or `nil` if no matching header exists. ## Examples iex> headers = [ ...> {"x-stream-offset", :long, 42}, ...> {"x-stream-filter-value", :longstr, "uuid"} ...> ] iex> NLdoc.Stream.Message.Header.find_value(headers, "x-stream-offset", :long) 42 iex> NLdoc.Stream.Message.Header.find_value(headers, "x-stream-filter-value", :longstr) "uuid" iex> NLdoc.Stream.Message.Header.find_value(headers, "x-stream-filter-value", :long) nil iex> NLdoc.Stream.Message.Header.find_value(headers, "non-existent", :long) nil """ @spec find_value(headers :: [t()], name :: String.t(), type :: :long) :: integer() | nil @spec find_value(headers :: [t()], name :: String.t(), type :: :longstr) :: String.t() | nil def find_value(headers, name, type), do: headers |> find(name, type) |> value() end