Dumbo.Decoder (Dumbo v0.3.0)

Copy Markdown View Source

Decoder implementation for the PHP serialisation format.

Summary

Functions

Deserialises a PHP serialised string into an Elixir term.

Types

decode_context()

@type decode_context() :: %Dumbo.Decoder.Context{
  opts: term(),
  position: term(),
  push?: term(),
  refs: term(),
  slot: term(),
  source: term()
}

opts()

@type opts() :: Dumbo.DecodeOpts.t()

Functions

decode(source, opts \\ %Dumbo.DecodeOpts{})

Deserialises a PHP serialised string into an Elixir term.

Accepts an optional %Dumbo.DecodeOpts{} struct. See Dumbo.DecodeOpts.

Examples

iex> Dumbo.Decoder.decode("N;")
nil

iex> Dumbo.Decoder.decode("b:0;")
false
iex> Dumbo.Decoder.decode("b:1;")
true

iex> Dumbo.Decoder.decode("i:685230;")
685230
iex> Dumbo.Decoder.decode("i:-685230;")
-685230

iex> Dumbo.Decoder.decode("d:685230.15;")
685230.15
iex> Dumbo.Decoder.decode("d:.5;")
0.5
iex> Dumbo.Decoder.decode("d:1e3;")
1.0e3
iex> Dumbo.Decoder.decode("d:1.0E+25;")
1.0e25
iex> Dumbo.Decoder.decode("d:INF;")
:infinity
iex> Dumbo.Decoder.decode("d:-INF;")
:negative_infinity
iex> Dumbo.Decoder.decode("d:NAN;")
:nan

iex> Dumbo.Decoder.decode(~s's:6:"foobar";')
"foobar"

iex> Dumbo.Decoder.decode(~s'a:2:{i:42;b:1;s:6:"A to Z";a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}}')
%{42 => true, "A to Z" => %{0 => 1, 1 => 2, 2 => 3}}
iex> Dumbo.Decoder.decode("a:0:{}")
%{}

iex> Dumbo.Decoder.decode(~s'O:8:"stdClass":2:{s:4:"John";d:3.14;s:4:"Jane";d:2.718;}')
%{"John" => 3.14, "Jane" => 2.718}

References are resolved as PHP resolves them, using a stack of every value pushed while decoding (arrays and objects included, keys excluded):

iex> Dumbo.Decoder.decode(~s'a:4:{i:0;i:10;i:1;i:20;i:2;i:30;i:3;R:2;}')
%{0 => 10, 1 => 20, 2 => 30, 3 => 10}

Common PHP classes are resolved into native Elixir types automatically. Supply an empty :object_resolvers map to receive raw objects instead:

iex> opts = %Dumbo.DecodeOpts{object_resolvers: %{}}
iex> Dumbo.Decoder.decode(~s'O:8:"stdClass":1:{s:3:"foo";s:3:"bar";}', opts)
{:object, "stdClass", %{"foo" => "bar"}}

Objects can also be decoded with the :object_resolvers option:

iex> opts = %Dumbo.DecodeOpts{object_resolvers: %{"stdClass" => fn obj -> obj end}}
iex> Dumbo.Decoder.decode(~s'O:8:"stdClass":1:{s:3:"foo";s:3:"bar";}', opts)
%{"foo" => "bar"}

Malformed input raises Dumbo.DecodeError pointing at the offending byte:

iex> Dumbo.Decoder.decode(~s'a:1:{i:0;i:1;x}')
** (Dumbo.DecodeError) unexpected sequence at position 13: "x"