ExMCP.Transport.Beam.Serializer (ex_mcp v0.9.2)

View Source

Serialization/deserialization for BEAM transport.

Supports multiple serialization formats optimized for different scenarios:

  • ETF (Erlang Term Format): Maximum performance for BEAM-to-BEAM communication
  • JSON: Cross-platform compatibility when needed
  • Protobuf: Future enhancement for schema evolution

ETF Advantages

  • Native BEAM optimization provides fastest serialization
  • Zero schema compilation required
  • Supports all Erlang/Elixir data types natively
  • Leverages "free serialization" in BEAM VM

Security

  • Uses :safe and :used options for ETF deserialization to prevent code injection
  • Enforces strict size limits (10MB max) to prevent resource exhaustion
  • Monitors atom table usage to prevent atom exhaustion attacks
  • Detects trailing data in ETF binaries to identify potential attacks
  • Handles serialization errors gracefully with detailed error reporting

Summary

Functions

Lists all available serialization formats.

Deserializes a binary using the specified format.

Estimates the serialized size of a message without actually serializing it. Useful for optimization decisions (zero-copy thresholds, etc.).

Checks if a format is available and properly configured.

Determines the best serialization format for the given scenario.

Serializes a message using the specified format.

Types

deserialization_result()

@type deserialization_result() :: {:ok, term()} | {:error, term()}

format()

@type format() :: :etf | :json | :protobuf

serialization_result()

@type serialization_result() :: {:ok, binary()} | {:error, term()}

Functions

available_formats()

@spec available_formats() :: [format()]

Lists all available serialization formats.

deserialize(binary, format)

@spec deserialize(binary(), format()) :: deserialization_result()

Deserializes a binary using the specified format.

Examples

iex> Serializer.deserialize(binary, :etf)
{:ok, %{method: "ping"}}

iex> Serializer.deserialize("{"method":"ping"}", :json)
{:ok, %{"method" => "ping"}}

estimate_size(message, atom)

@spec estimate_size(term(), format()) :: integer()

Estimates the serialized size of a message without actually serializing it. Useful for optimization decisions (zero-copy thresholds, etc.).

format_available?(atom)

@spec format_available?(format()) :: boolean()

Checks if a format is available and properly configured.

optimal_format(arg1, arg2)

@spec optimal_format(atom(), atom()) :: format()

Determines the best serialization format for the given scenario.

Examples

iex> Serializer.optimal_format(:local, :beam_to_beam)
:etf

iex> Serializer.optimal_format(:distributed, :cross_platform)
:json

serialize(message, atom)

@spec serialize(term(), format()) :: serialization_result()

Serializes a message using the specified format.

Examples

iex> Serializer.serialize(%{method: "ping"}, :etf)
{:ok, <<131, 116, 0, 0, 0, 1, 100, 0, 6, 109, 101, 116, 104, 111, 100, 109, 0, 0, 0, 4, 112, 105, 110, 103>>}

iex> Serializer.serialize(%{method: "ping"}, :json)
{:ok, "{"method":"ping"}"}