     end
   end
 
+  @spec field(t, integer | atom) :: any
+
   def field(pdu, id_or_name) do
     mandatory_field(pdu, id_or_name) || optional_field(pdu, id_or_name)
   end
 
+  @spec optional_fields(t) :: map
+
   def optional_fields(pdu), do: pdu.optional
+
+  @spec mandatory_fields(t) :: map
 
   def mandatory_fields(pdu), do: pdu.mandatory
 

    }
  end

  def command_id(pdu) do
    pdu.command_id
  end

  def command_status(pdu) do
    pdu.command_status
  end

  def sequence_number(pdu) do
    pdu.sequence_number
  end

  def mandatory_field(pdu, name) when is_atom(name) do
    pdu.mandatory[name]
  end

  def optional_field(pdu, id) when is_integer(id) do
    pdu.optional[id]

defmodule SMPPEX.Pdu do
  alias SMPPEX.Protocol.TlvFormat
  alias SMPPEX.Protocol.CommandNames
  alias SMPPEX.Pdu

  @type t :: %Pdu{
    command_id: integer,
    command_status: integer,
    sequence_number: integer,
    mandatory: map,
    optional: map
  }

  defstruct [
