Iconvex (iconvex v0.1.1)

Copy Markdown View Source

Pure BEAM character-set conversion based on GNU libiconv 1.19.

convert/4 performs complete, one-shot conversion. stream/4 provides lazy, bounded-memory conversion with incremental state for built-in stateless and stateful codecs. The older new/3, feed/2, and finish/1 API remains a buffered transaction whose final result is exactly one convert/4 call.

Summary

Functions

Resolves an encoding name, alias, built-in ID, or registered codec module.

Equivalent to convert/4 with default options.

Converts a complete encoded binary.

Equivalent to convert!/4 with default options.

Converts a complete binary, raising for conversion or request errors.

Returns all currently registered canonical encoding names.

Adds a binary chunk in O(1) time.

Performs the buffered conversion and returns its final output.

Finalizes a buffered converter and returns its terminal state.

Equivalent to new/3 with default options.

Creates a buffered chunked converter.

Registers a codec implemented by an external library.

Atomically registers a codec only when that module is not already registered.

Registers a codec and returns an ownership token for conditional cleanup.

Equivalent to stream/4 with default options.

Creates a lazy, bounded-memory conversion stream.

Equivalent to stream/4, returning the stream or raising for request errors.

Removes a previously registered external codec.

Removes a codec only when token owns its current registration.

Types

conversion_option()

@type conversion_option() ::
  {:invalid, :error | :discard}
  | {:unrepresentable, :error | :discard}
  | {:transliterate, boolean()}
  | {:byte_substitute, nil | binary()}
  | {:unicode_substitute, nil | binary()}
  | {:on_invalid_byte, nil | invalid_byte_handler()}
  | {:from_surface, nil | :zos_unix}
  | {:to_surface, nil | :zos_unix}

conversion_options()

@type conversion_options() :: [conversion_option()]

conversion_result()

@type conversion_result() ::
  {:ok, binary()} | {:error, Iconvex.Error.t() | request_error()}

encoding()

@type encoding() :: String.t() | atom()

invalid_byte_handler()

@type invalid_byte_handler() :: (Iconvex.InvalidByte.t() ->
                             :default
                             | :error
                             | :discard
                             | {:replace, invalid_byte_replacement()})

invalid_byte_replacement()

@type invalid_byte_replacement() :: binary() | non_neg_integer() | [non_neg_integer()]

registration_token()

@type registration_token() :: reference()

request_error()

@type request_error() ::
  :unknown_encoding
  | :already_finished
  | {:invalid_argument, atom()}
  | {:invalid_options, :expected_keyword}
  | {:invalid_option, atom(), term()}
  | {:invalid_callback_return, atom(), term()}
  | {:invalid_codec_callback_return, module(), {atom(), non_neg_integer()},
     term()}
  | {:streaming_unsupported, :source | :target, String.t()}
  | {:invalid_suffix, String.t()}

Functions

canonical_name(name)

@spec canonical_name(encoding()) :: {:ok, String.t()} | :error

Resolves an encoding name, alias, built-in ID, or registered codec module.

convert(input, from, to)

@spec convert(binary(), encoding(), encoding()) :: conversion_result()

Equivalent to convert/4 with default options.

convert(input, from, to, options)

Converts a complete encoded binary.

Invalid options and suffixes return typed request errors. Malformed source input returns Iconvex.Error. Destination handling follows GNU libiconv: ordinary unavailable characters error, while extended UCS values use U+FFFD when the destination family defines that fallback and can encode it. Discard, transliteration, and substitution options take precedence over the fallback. GNU suffixes such as //IGNORE, //NON_IDENTICAL_DISCARD, and //TRANSLIT may be appended to encoding names.

convert!(input, from, to)

@spec convert!(binary(), encoding(), encoding()) :: binary()

Equivalent to convert!/4 with default options.

convert!(input, from, to, options)

@spec convert!(binary(), encoding(), encoding(), conversion_options()) :: binary()

Converts a complete binary, raising for conversion or request errors.

encodings()

@spec encodings() :: [String.t()]

Returns all currently registered canonical encoding names.

feed(converter, chunk)

@spec feed(Iconvex.Converter.t(), binary()) ::
  {:ok, binary(), Iconvex.Converter.t()} | {:error, request_error()}

Adds a binary chunk in O(1) time.

Output is intentionally empty until finalization. Full buffering is the contract that makes chunked conversion exactly equivalent to convert/4 across every possible byte split.

finish(converter)

@spec finish(Iconvex.Converter.t()) :: conversion_result()

Performs the buffered conversion and returns its final output.

Errors use byte offsets from the beginning of the complete stream. Because Elixir values are immutable, this compatibility function cannot mark the caller's converter finished; use finish_with_state/1 when lifecycle checks are required.

finish_with_state(converter)

@spec finish_with_state(Iconvex.Converter.t()) ::
  {:ok, binary(), Iconvex.Converter.t()}
  | {:error, Iconvex.Error.t() | request_error()}

Finalizes a buffered converter and returns its terminal state.

new(from, to)

@spec new(encoding(), encoding()) ::
  {:ok, Iconvex.Converter.t()} | {:error, request_error()}

Equivalent to new/3 with default options.

new(from, to, options)

@spec new(encoding(), encoding(), conversion_options()) ::
  {:ok, Iconvex.Converter.t()} | {:error, request_error()}

Creates a buffered chunked converter.

Encoding entries and table-provider routing are resolved once, so a converter remains stable if an external codec or its provider is later unregistered, replaced, or stopped.

register_codec(module, options \\ [])

@spec register_codec(
  module(),
  keyword()
) :: :ok | {:error, term()}

Registers a codec implemented by an external library.

:canonical can replace the module's declared canonical name for this registration. This lets independent sources expose colliding codec names under source-qualified names without overriding a built-in. Module and option aliases remain active and subject to the normal conflict checks.

register_codec_if_absent(module, options \\ [])

@spec register_codec_if_absent(
  module(),
  keyword()
) :: {:ok, registration_token() | :existing} | {:error, term()}

Atomically registers a codec only when that module is not already registered.

Returns {:ok, token} for a new registration or {:ok, :existing} without replacing caller-owned metadata. Pass a returned token to unregister_codec/2 during application shutdown. Registration replacement has one externally visible commit point, so concurrent lookups see either the complete old entry or the complete new entry.

register_codec_owned(module, options \\ [])

@spec register_codec_owned(
  module(),
  keyword()
) :: {:ok, registration_token()} | {:error, term()}

Registers a codec and returns an ownership token for conditional cleanup.

This variant retains register_codec/2 replacement semantics. A library should normally prefer register_codec_if_absent/2 during application start. Registrations and their tokens survive a supervised registry-worker restart while the :iconvex application remains running.

stream(enumerable, from, to)

@spec stream(Enumerable.t(), encoding(), encoding()) ::
  {:ok, Enumerable.t()} | {:error, request_error()}

Equivalent to stream/4 with default options.

stream(enumerable, from, to, options)

@spec stream(Enumerable.t(), encoding(), encoding(), conversion_options()) ::
  {:ok, Enumerable.t()} | {:error, request_error()}

Creates a lazy, bounded-memory conversion stream.

Input enumerable must emit binaries. Output stream emits converted binaries as source chunks become stable. Conversion errors raise Iconvex.Error during enumeration because earlier output may already have been consumed.

Built-in stateful codecs carry designation, shift, Base64, and BOM state across chunks. External codecs opt in through the incremental callbacks in Iconvex.Codec; a missing callback returns {:streaming_unsupported, role, encoding} instead of silently buffering.

stream!(enumerable, from, to, options \\ [])

Equivalent to stream/4, returning the stream or raising for request errors.

unregister_codec(module)

@spec unregister_codec(module()) :: :ok | {:error, term()}

Removes a previously registered external codec.

unregister_codec(module, token)

@spec unregister_codec(module(), registration_token()) :: :ok | {:error, term()}

Removes a codec only when token owns its current registration.