Whiff.Input (whiff v0.1.0)

Copy Markdown View Source

Canonical description of one extraction input for Elixir plugins.

Built by the public API before native extraction and passed to Whiff.Extractor / Whiff.Analyzer callbacks. Prefer deciding supports?/2 from descriptors (:extension, :filename, :size) instead of reading entire large files.

Fields

  • :source — :path or :binary
  • :path — absolute or relative filesystem path when source: :path
  • :bytes — payload when source: :binary (may be large; do not log it)
  • :filename — basename used for detection and supports?/2
  • :extension — lowercase extension including the dot (e.g. ".pdf"), or nil
  • :mime — optional caller-supplied MIME type
  • :size — byte size when known

Examples

iex> input = Whiff.Input.from_path("/tmp/report.pdf")
iex> input.source
:path
iex> input.filename
"report.pdf"
iex> input.extension
".pdf"

iex> {:ok, input} = ok_binary()
iex> input.source
:binary
iex> input.extension
".trade"
iex> Map.has_key?(Whiff.Input.present(input), :bytes)
false

The helper below is only for doctests:

iex> false
false

Summary

Types

Whether the payload is on disk or already in memory.

t()

Input struct passed to Elixir plugins. See the module doc for fields.

Functions

Builds input from in-memory bytes.

Builds input from a filesystem path.

Safe presentation map for logs and diagnostics.

Types

source()

@type source() :: :path | :binary

Whether the payload is on disk or already in memory.

t()

@type t() :: %Whiff.Input{
  bytes: binary() | nil,
  extension: String.t() | nil,
  filename: String.t() | nil,
  mime: String.t() | nil,
  path: String.t() | nil,
  size: non_neg_integer() | nil,
  source: source()
}

Input struct passed to Elixir plugins. See the module doc for fields.

Functions

from_binary(bytes, opts \\ [])

@spec from_binary(binary(), keyword()) :: t() | {:error, Whiff.Error.t()}

Builds input from in-memory bytes.

Arguments

  • bytes — binary payload
  • opts — optional keywords:
    • :name / :filename — basename for detection (default "input.bin")
    • :mime — optional MIME string

Returns

  • %Whiff.Input{} on success
  • {:error, %Whiff.Error{reason: :invalid_option}} if :name is present but not a binary
  • {:error, %Whiff.Error{reason: :unsupported_input}} if bytes is not a binary

Examples

iex> input = Whiff.Input.from_binary("TRADE/1\nid=1\n", name: "pos.trade")
iex> match?(%Whiff.Input{source: :binary, extension: ".trade", size: 14}, input)
true

iex> Whiff.Input.from_binary("x", name: :bad)
{:error, %Whiff.Error{reason: :invalid_option, message: "name must be a string", path: nil, details: %{}}}

iex> Whiff.Input.from_binary(:not_a_binary)
{:error, %Whiff.Error{reason: :unsupported_input, message: "expected a binary", path: nil, details: %{}}}

from_path(path)

@spec from_path(Path.t()) :: t()

Builds input from a filesystem path.

Does not read file contents. :size is filled from File.stat/1 when the path exists; otherwise nil.

Arguments

  • path — UTF-8 path string

Examples

iex> i = Whiff.Input.from_path("docs/notes.TXT")
iex> {i.source, i.filename, i.extension}
{:path, "notes.TXT", ".txt"}

present(input)

@spec present(t()) :: map()

Safe presentation map for logs and diagnostics.

Never includes :bytes.

Examples

iex> input = Whiff.Input.from_binary(<<0, 1, 2>>, name: "x.bin", mime: "application/octet-stream")
iex> Whiff.Input.present(input)
%{source: :binary, path: nil, filename: "x.bin", extension: ".bin", mime: "application/octet-stream", size: 3}