From 42e78f95820be3c13cb6e376d068bdb2d16da69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=9Aled=C5=BA?= Date: Tue, 24 Oct 2023 21:36:37 +0200 Subject: [PATCH] Add ExSDP.get_attribute(s)/2 (#37) --- lib/ex_sdp.ex | 9 ++++++- lib/ex_sdp/media.ex | 50 +++-------------------------------- lib/ex_sdp/utils.ex | 53 ++++++++++++++++++++++++++++++++++++++ test/ex_sdp/media_test.exs | 2 +- test/sdp_test.exs | 38 +++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 48 deletions(-) diff --git a/lib/ex_sdp.ex b/lib/ex_sdp.ex index faf5033..68448b5 100644 --- a/lib/ex_sdp.ex +++ b/lib/ex_sdp.ex @@ -19,7 +19,8 @@ defmodule ExSDP do RepeatTimes, Serializer, Timezone, - Timing + Timing, + Utils } @enforce_keys [:origin] @@ -101,6 +102,12 @@ defmodule ExSDP do @spec add_attributes(sdp :: t(), attributes :: [Attribute.t()]) :: t() def add_attributes(sdp, attributes) when is_list(attributes), do: Map.update!(sdp, :attributes, &(&1 ++ attributes)) + + @spec get_attribute(sdp :: t(), key :: module() | atom() | binary()) :: Attribute.t() | nil + def get_attribute(sdp, key), do: Utils.get_attribute(sdp, key) + + @spec get_attributes(sdp :: t(), key :: module() | atom() | binary()) :: [Attribute.t()] + def get_attributes(sdp, key), do: Utils.get_attributes(sdp, key) end defimpl String.Chars, for: ExSDP do diff --git a/lib/ex_sdp/media.ex b/lib/ex_sdp/media.ex index e3ec634..ed4fa1f 100644 --- a/lib/ex_sdp/media.ex +++ b/lib/ex_sdp/media.ex @@ -11,18 +11,8 @@ defmodule ExSDP.Media do Attribute, Bandwidth, ConnectionData, - Encryption - } - - alias ExSDP.Attribute.{ - Extmap, - FMTP, - Group, - MSID, - RTCPFeedback, - RTPMapping, - SSRC, - SSRCGroup + Encryption, + Utils } @enforce_keys [:type, :port, :protocol, :fmt] @@ -57,18 +47,6 @@ defmodule ExSDP.Media do """ @type type :: :audio | :video | :text | :application | :message | binary() - # For searching struct attributes by atoms - @struct_attr_keys %{ - :rtpmap => RTPMapping, - :msid => MSID, - :fmtp => FMTP, - :ssrc => SSRC, - :ssrc_group => SSRCGroup, - :rtcp_feedback => RTCPFeedback, - :group => Group, - :extmap => Extmap - } - @spec new( type :: type(), port :: :inet.port_number(), @@ -94,30 +72,10 @@ defmodule ExSDP.Media do do: Map.update!(media, :attributes, &(&1 ++ attributes)) @spec get_attribute(media :: t(), key :: module() | atom() | binary()) :: Attribute.t() | nil - def get_attribute(media, key) do - key = Map.get(@struct_attr_keys, key, key) - - media.attributes - |> Enum.find(fn - %module{} -> module == key - {k, _v} -> k == key - # for flag attributes - k -> k == key - end) - end + def get_attribute(media, key), do: Utils.get_attribute(media, key) @spec get_attributes(media :: t(), key :: module() | atom() | binary()) :: [Attribute.t()] - def get_attributes(media, key) do - key = Map.get(@struct_attr_keys, key, key) - - media.attributes - |> Enum.filter(fn - %module{} -> module == key - {k, _v} -> k == key - # for flag attributes - k -> k == key - end) - end + def get_attributes(media, key), do: Utils.get_attributes(media, key) @spec parse(binary()) :: {:ok, t()} | {:error, :invalid_media_spec | :malformed_port_number} def parse(media) do diff --git a/lib/ex_sdp/utils.ex b/lib/ex_sdp/utils.ex index 108c34a..47a69e3 100644 --- a/lib/ex_sdp/utils.ex +++ b/lib/ex_sdp/utils.ex @@ -1,6 +1,59 @@ defmodule ExSDP.Utils do @moduledoc false + alias ExSDP.{Attribute, Media} + + alias ExSDP.Attribute.{ + Extmap, + FMTP, + Group, + MSID, + RTCPFeedback, + RTPMapping, + SSRC, + SSRCGroup + } + + # For searching struct attributes by atoms + @struct_attr_keys %{ + :extmap => Extmap, + :fmtp => FMTP, + :group => Group, + :msid => MSID, + :rtcp_feedback => RTCPFeedback, + :rtpmap => RTPMapping, + :ssrc => SSRC, + :ssrc_group => SSRCGroup + } + + @spec get_attribute(sdp_or_media :: ExSDP.t() | Media.t(), key :: module() | atom() | binary()) :: + Attribute.t() | nil + def get_attribute(sdp_or_media, key) do + key = Map.get(@struct_attr_keys, key, key) + + sdp_or_media.attributes + |> Enum.find(fn + %module{} -> module == key + {k, _v} -> k == key + # for flag attributes + k -> k == key + end) + end + + @spec get_attributes(sdp_or_media :: ExSDP.t() | Media.t(), key :: module() | atom() | binary()) :: + [Attribute.t()] + def get_attributes(sdp_or_media, key) do + key = Map.get(@struct_attr_keys, key, key) + + sdp_or_media.attributes + |> Enum.filter(fn + %module{} -> module == key + {k, _v} -> k == key + # for flag attributes + k -> k == key + end) + end + @spec split(String.t(), String.t() | [String.t()] | :binary.cp() | Regex.t(), any) :: {:error, :too_few_fields} | {:ok, [String.t()]} def split(origin, delim, expected_len) do diff --git a/test/ex_sdp/media_test.exs b/test/ex_sdp/media_test.exs index 5a464ba..8d33213 100644 --- a/test/ex_sdp/media_test.exs +++ b/test/ex_sdp/media_test.exs @@ -256,7 +256,7 @@ defmodule ExSDP.MediaTest do end describe "Utils functions" do - test "gets attribute by module" do + test "gets attribute by atom or module" do rtpmap = %RTPMapping{clock_rate: 8000, encoding: "L8", params: 1, payload_type: 96} ssrc = %SSRC{id: 12_345, attribute: "cname", value: "HPd3XfRHXYUxzfsJ"} diff --git a/test/sdp_test.exs b/test/sdp_test.exs index f334ce7..d1e25c4 100644 --- a/test/sdp_test.exs +++ b/test/sdp_test.exs @@ -187,4 +187,42 @@ defmodule ExSDPTest do end end end + + describe "get_attribute/2" do + test "gets attribute by atom, binary or module" do + sdp = + ExSDP.new() + |> ExSDP.add_attribute({"key", "value"}) + |> ExSDP.add_attribute(:recvonly) + |> ExSDP.add_attribute(%ExSDP.Attribute.Group{semantics: "BUNDLE", mids: [0, 1, 2]}) + + assert :recvonly == ExSDP.get_attribute(sdp, :recvonly) + assert {"key", "value"} == ExSDP.get_attribute(sdp, "key") + + assert %ExSDP.Attribute.Group{semantics: "BUNDLE", mids: [0, 1, 2]} == + ExSDP.get_attribute(sdp, ExSDP.Attribute.Group) + + assert %ExSDP.Attribute.Group{semantics: "BUNDLE", mids: [0, 1, 2]} == + ExSDP.get_attribute(sdp, :group) + + assert nil == ExSDP.get_attribute(sdp, :non_existing_atom) + assert nil == ExSDP.get_attribute(sdp, ExSDP.Attribute.NonExistingModule) + assert nil == ExSDP.get_attribute(sdp, "non_existing_string") + end + end + + describe "get_attributes/2" do + test "gets multiple attributes by module" do + sdp = + ExSDP.new() + |> ExSDP.add_attribute(%ExSDP.Attribute.Group{semantics: "BUNDLE", mids: [0, 1, 2]}) + |> ExSDP.add_attribute(%ExSDP.Attribute.Group{semantics: "BUNDLE", mids: [3, 4, 5]}) + + assert [ + %ExSDP.Attribute.Group{semantics: "BUNDLE", mids: [0, 1, 2]}, + %ExSDP.Attribute.Group{semantics: "BUNDLE", mids: [3, 4, 5]} + ] == + ExSDP.get_attributes(sdp, ExSDP.Attribute.Group) + end + end end