Packages

Elixir bindings for pdf_oxide, a high-performance PDF library written in Rust.

Current section

Files

Jump to
pdf_elixide lib pdf_elixide.ex
Raw

lib/pdf_elixide.ex

defmodule PdfElixide do
@moduledoc """
Elixir bindings for pdf_oxide, a high-performance PDF library written in Rust.
"""
@opaque t :: reference()
@doc """
Opens a PDF document from the specified file path.
"""
@spec open(Path.t()) :: {:ok, t()} | {:error, term()}
def open(path) when is_binary(path) do
wrap(fn -> PdfElixide.Native.open(path) end)
end
@doc """
Opens a PDF document from the specified file path, raising an error if it fails.
"""
@spec open!(Path.t()) :: t()
def open!(path) when is_binary(path) do
case open(path) do
{:ok, doc} -> doc
{:error, reason} -> raise "Failed to open PDF: #{inspect(reason)}"
end
end
@doc """
Opens a PDF document from the given binary data.
"""
@spec from_binary(binary()) :: {:ok, t()} | {:error, term()}
def from_binary(bytes) when is_binary(bytes) do
wrap(fn -> PdfElixide.Native.from_bytes(bytes) end)
end
@doc """
Opens a PDF document from the given binary data, raising an error if it fails.
"""
@spec from_binary!(binary()) :: t()
def from_binary!(bytes) when is_binary(bytes) do
case from_binary(bytes) do
{:ok, doc} -> doc
{:error, reason} -> raise "Failed to open PDF from binary: #{inspect(reason)}"
end
end
@doc """
Returns the number of pages in the given PDF document.
"""
@spec page_count(t()) :: {:ok, non_neg_integer()} | {:error, term()}
def page_count(doc) when is_reference(doc) do
wrap(fn -> PdfElixide.Native.page_count(doc) end)
end
@doc """
Returns the number of pages in the given PDF document, raising an error if it fails.
"""
@spec page_count!(t()) :: non_neg_integer()
def page_count!(doc) when is_reference(doc) do
case page_count(doc) do
{:ok, count} -> count
{:error, reason} -> raise "Failed to get page count: #{inspect(reason)}"
end
end
@doc """
Returns the PDF specification version of the given document as a `{major, minor}` tuple.
"""
@spec version(t()) :: {:ok, {non_neg_integer(), non_neg_integer()}} | {:error, term()}
def version(doc) when is_reference(doc) do
wrap(fn -> PdfElixide.Native.version(doc) end)
end
@doc """
Returns the PDF specification version of the given document, raising an error if it fails.
"""
@spec version!(t()) :: {non_neg_integer(), non_neg_integer()}
def version!(doc) when is_reference(doc) do
case version(doc) do
{:ok, ver} -> ver
{:error, reason} -> raise "Failed to get PDF version: #{inspect(reason)}"
end
end
@doc """
Extracts the text content of the page at the given zero-based index.
"""
@spec extract_text(t(), non_neg_integer()) :: {:ok, binary()} | {:error, term()}
def extract_text(doc, page_index)
when is_reference(doc) and is_integer(page_index) and page_index >= 0 do
wrap(fn -> PdfElixide.Native.extract_text(doc, page_index) end)
end
@doc """
Extracts the text content of the page at the given zero-based index,
raising an error if it fails.
"""
@spec extract_text!(t(), non_neg_integer()) :: binary()
def extract_text!(doc, page_index)
when is_reference(doc) and is_integer(page_index) and page_index >= 0 do
case extract_text(doc, page_index) do
{:ok, text} -> text
{:error, reason} -> raise "Failed to extract text: #{inspect(reason)}"
end
end
# NIF result wrapper
defp wrap(fun) do
case fun.() do
# NIF returned tagged ok
{:ok, _} = result -> result
# NIF returned tagged error
{:error, _} = result -> result
# NIF returned a bare value
other -> {:ok, other}
end
rescue
# Argument error from Rustler
ArgumentError -> {:error, :badarg}
# Structured Rust-side error via Error::Term
e in ErlangError -> {:error, e.original}
# Anything else (RuntimeError, FunctionClauseError, ...)
e -> {:error, Exception.message(e)}
end
end