Packages
smppex
3.2.0
3.3.0
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
retired
3.1.0
retired
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.4.0
2.3.3
2.3.2
2.3.1
2.3.0
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.1.0
2.0.1
2.0.0
1.0.1
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
SMPP 3.4 protocol and framework implemented in Elixir
Retired package: Invalid changelog
Current section
Files
Jump to
Current section
Files
lib/smppex/protocol/optional_fields_parser.ex
defmodule SMPPEX.Protocol.OptionalFieldsParser do
@moduledoc false
alias SMPPEX.Protocol.Unpack
alias SMPPEX.Protocol.TlvFormat
@type parse_result :: {:ok, map} | {:error, reason :: term}
@spec parse(binary) :: parse_result
def parse(bin), do: parse(bin, Map.new())
defp parse(<<>>, parsed_fields) do
{:ok, parsed_fields}
end
defp parse(bin, parsed_fields) do
case Unpack.tlv(bin) do
{:ok, {tag, value}, rest} ->
case parse_format(tag, value) do
{:ok, parsed} ->
parse(rest, Map.put(parsed_fields, tag, parsed))
{:error, error} ->
{:error, {"Invalid format for tlv #{inspect(tag)}", error}}
end
{:error, _} = err ->
err
end
end
defp parse_format(tag, value) do
case TlvFormat.format_by_id(tag) do
{:ok, format} ->
parse_known_tlv(value, format)
# unknown tlvs are always valid
:unknown ->
{:ok, value}
end
end
defp parse_known_tlv(value, {:integer, size}) do
bit_length = size * 8
case value do
<<int::big-unsigned-integer-size(bit_length)>> -> {:ok, int}
_ -> {:error, "Invalid integer"}
end
end
defp parse_known_tlv(value, {:c_octet_string, {:max, size}}) do
case Unpack.c_octet_string(value, {:max, size}) do
{:ok, str, ""} -> {:ok, str}
_ -> {:error, "Invalid c_octet_string"}
end
end
defp parse_known_tlv(value, {:octet_string, size}) when is_integer(size) do
case value do
<<_::binary-size(size)>> -> {:ok, value}
_ -> {:error, "Invalid octet_string"}
end
end
defp parse_known_tlv(value, {:octet_string, {from, to}}) do
if byte_size(value) >= from and byte_size(value) <= to do
{:ok, value}
else
{:error, "Invalid octet_string"}
end
end
end