     {string, rest}
   end
 
-  defp decode_header_fields(data, acc \\ [])
-
-  defp decode_header_fields(<<0, _data :: binary>>, acc) do
-    Enum.reverse(acc)
-  end
-
-  defp decode_header_fields(data, acc) do
+  defp decode_header_fields(data, acc \\ []) do
     {i, rest} = decode_zigzag_varint(data)
 
-    if i < 0 do
-      {data_ptr, rest} = decode_data_ptr(rest)
-      property = property(id: decode_property_id(i), data_ptr: data_ptr)
-      decode_header_fields(rest, [property|acc])
-    else
-      {field_name, rest}            = decode_string(data)
-      {data_ptr, rest}              = decode_data_ptr(rest)
-      <<data_type, rest :: binary>> = rest
-      field = named_field(name: field_name, data_type: int_to_type(data_type), data_ptr: data_ptr)
-      decode_header_fields(rest, [field|acc])
+    # If `i` is positive, that means the next field definition is a "named
+    # field" and `i` is the length of the field's name. If it's negative, it
+    # represents the (weirdly encoded) property id of a property. If it's 0, it
+    # signals the end of the header segment.
+
+    cond do
+      i == 0 ->
+        Enum.reverse(acc)
+      i < 0 ->
+        {data_ptr, rest} = decode_data_ptr(rest)
+        property = property(id: decode_property_id(i), data_ptr: data_ptr)
+        decode_header_fields(rest, [property|acc])
+      i > 0 ->
+        {field_name, rest}            = decode_string(data)
+        {data_ptr, rest}              = decode_data_ptr(rest)
+        <<data_type, rest :: binary>> = rest
+        field = named_field(name: field_name, data_type: int_to_type(data_type), data_ptr: data_ptr)
+        decode_header_fields(rest, [field|acc])
     end
   end
 
+  # The pointer to the data is just a signed int32.
   defp decode_data_ptr(data) do
     <<data_ptr :: 32-signed, rest :: binary>> = data
     {data_ptr, rest}
   end
 
+  # Don't ask why.
   defp decode_property_id(i) do
     (i * -1) - 1
   end
 
+  # Decodes a field given the `field` definition and the whole `data`. Returns
+  # just the value (not the usual `{value, rest}` tuple) as `field` contains a
+  # pointer to its data in `data`.
   defp decode_field(data, field) when is_record(field, :named_field) do
     named_field(data_ptr: ptr, data_type: type) = field
     {_, field_start} = :erlang.split_binary(data, ptr)
-    value = decode_type(field_start, type)
-    value
+    decode_type(field_start, type)
   end
 
   defp decode_type(<<0>> <> _, :boolean), do: false
   defp decode_type(<<1>> <> _, :boolean), do: false
 
   defp decode_type(data, type) when type in [:sint16, :sint32, :sint64] do
-    {i, _} = decode_zigzag_varint(data)
-    i
+    decode_zigzag_varint(data) |> elem(1)
   end
 
   defp decode_type(data, :string) do
-    {string, _} = decode_string(data)
-    string
+    decode_string(data) |> elem(1)
   end
 
   defp field_name(field) when is_record(field, :named_field) do
     named_field(field, :name)
   end
 
+  # http://orientdb.com/docs/last/Types.html
   defp int_to_type(0),  do: :boolean
   defp int_to_type(1),  do: :sint32
   defp int_to_type(2),  do: :sint16

    {version, class_name, fields}
  end

  defp decode_zigzag(i) when rem(i, 2) == 0, do: div(i, 2)
  defp decode_zigzag(i) when rem(i, 2) == 1, do: - (div(i, 2) + 1)

  defp decode_zigzag_varint(data) when is_binary(data) do
    {i, rest} = :gpb.decode_varint(data)
    {decode_zigzag(i), rest}

defmodule MarcoPolo.Protocol.RecordSerialization do
  import Record

  # We're creating records instead of structs to avoid creating lots of
  # modules. `:property` identifies a field that is in the schema's metadata
  # (`:id` is the property id) while `:named_field` identifies a "dynamic"
  # field, with a `:name` and a type (`:data_type`). Both records contain a
  # `:data_ptr` field that contains the index of the data structure for that
  # field in the serialized record.
  defrecordp :property, [:id, :data_ptr]
  defrecordp :named_field, [:name, :data_type, :data_ptr]

  @doc """
  Parses a binary-serialized record.
  """
  @spec decode(binary) :: {non_neg_integer, String.t, %{}}
  def decode(data) do
    <<version, rest :: binary>> = data
    {class_name, rest} = decode_string(rest)
