Skip to content

Commit

Permalink
Merge pull request #21 from avencera/atom
Browse files Browse the repository at this point in the history
Add support for parsing Atom feeds
  • Loading branch information
praveenperera committed Sep 8, 2023
2 parents 1cf81a4 + bdb6628 commit ea81ac6
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 75 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- Add support for parsing Atom feeds (`parse_atom/1`)
- Deprecate `parse/1` function in favor or `parse_rss/1` function

## [0.4.4] – 2022-11-25

- Attempt to fix precompiled assets for case sensitive filesystems again
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ It can be installed by adding `fast_rss` to your list of dependencies in `mix.ex
```elixir
def deps do
[
{:fast_rss, "~> 0.4.0"}
{:fast_rss, "~> 0.5.0"}
]
end
```
Expand All @@ -67,10 +67,10 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

## Usage

There is only one function it takes an RSS string and outputs an `{:ok, map()}` with string keys.
There is only two functions, one for parsing rss `parse_rss/1` and one for parsing atom feeds `parse_atom/1` they takes a string and outputs an `{:ok, map()}` with string keys.

```elixir
iex(1)> {:ok, map_of_rss} = FastRSS.parse("...rss_feed_string...")
iex(1)> {:ok, map_of_rss} = FastRSS.parse_rss("...rss_feed_string...")
iex(2)> Map.keys(map_of_rss)
["categories", "cloud", "copyright", "description", "docs", "dublin_core_ext",
"extensions", "generator", "image", "items", "itunes_ext", "language",
Expand All @@ -92,6 +92,7 @@ Reading from the following RSS versions is supported:
- RSS 2.0
- iTunes
- Dublin Core
- Atom

## Benchmark

Expand Down
2 changes: 1 addition & 1 deletion bench/bench.exs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ elixir_feed_parser = fn xml_string ->
end

parse_jobs = %{
"fast_rss" => &FastRSS.parse/1,
"fast_rss" => &FastRSS.parse_rss/1,
"elixir_feed_parser" => fn string -> elixir_feed_parser.(string) end,
"feed_raptor" => &Feedraptor.parse/1,
"feeder_ex" => &FeederEx.parse/1
Expand Down
37 changes: 33 additions & 4 deletions lib/fast_rss.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,51 @@ defmodule FastRSS do
version: version

# When your NIF is loaded, it will override this function.
def parse(_a), do: :erlang.nif_error(:nif_not_loaded)
def parse_rss(_a), do: :erlang.nif_error(:nif_not_loaded)
def parse_atom(_a), do: :erlang.nif_error(:nif_not_loaded)
end

@doc """
Parse a RSS string into a map.
soft deprecated: "Use FastRSS.parse_rss/1 instead"
@doc since: "0.5.0"
@deprecated "Use FastRSS.parse_rss/1 instead"
"""
@spec parse(String.t()) :: {:ok, map()} | {:error, String.t()}
def parse(""), do: {:error, "Cannot parse blank string"}
def parse(rss_string) when is_binary(rss_string), do: parse_rss(rss_string)
def parse(_something_else), do: {:error, "RSS feed must be passed in as a string"}

@doc """
Parse a RSS string into a map.
"""
@spec parse_rss(String.t()) :: {:ok, map()} | {:error, String.t()}
@doc since: "0.5.0"
def parse_rss(""), do: {:error, "Cannot parse blank string"}

def parse(rss_string) when is_binary(rss_string) do
def parse_rss(rss_string) when is_binary(rss_string) do
rss_string
|> Native.parse()
|> Native.parse_rss()
|> map_to_tuple()
end

def parse_rss(_something_else), do: {:error, "RSS feed must be passed in as a string"}

@doc """
Parse a Atom string into a map.
"""
@spec parse_atom(String.t()) :: {:ok, map()} | {:error, String.t()}
@doc since: "0.5.0"
def parse_atom(""), do: {:error, "Cannot parse blank string"}

def parse_atom(atom_string) when is_binary(atom_string) do
atom_string
|> Native.parse_atom()
|> map_to_tuple()
end

def parse(_somethig_else), do: {:error, "RSS feed must be passed in as a string"}
def parse_atom(_something_else), do: {:error, "Atom feed must be passed in as a string"}

defp map_to_tuple(%{"Ok" => map}), do: {:ok, map}
defp map_to_tuple({:ok, map}), do: {:ok, map}
Expand Down
6 changes: 3 additions & 3 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule FastRSS.MixProject do
use Mix.Project

@source_url "https://github.com/avencera/fast_rss"
@version "0.4.4"
@version "0.5.0"

def project do
[
Expand Down Expand Up @@ -69,8 +69,8 @@ defmodule FastRSS.MixProject do
defp deps do
[
# rust
{:rustler, "~> 0.25.0", optional: true},
{:rustler_precompiled, "~> 0.5"},
{:rustler, "~> 0.29.0", optional: true},
{:rustler_precompiled, "~> 0.6"},

# docs
{:ex_doc, ">= 0.0.0", only: :dev, runtime: false}
Expand Down
18 changes: 9 additions & 9 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
%{
"castore": {:hex, :castore, "0.1.19", "a2c3e46d62b7f3aa2e6f88541c21d7400381e53704394462b9fd4f06f6d42bb6", [:mix], [], "hexpm", "e96e0161a5dc82ef441da24d5fa74aefc40d920f3a6645d15e1f9f3e66bb2109"},
"castore": {:hex, :castore, "1.0.3", "7130ba6d24c8424014194676d608cb989f62ef8039efd50ff4b3f33286d06db8", [:mix], [], "hexpm", "680ab01ef5d15b161ed6a95449fac5c6b8f60055677a8e79acf01b27baa4390b"},
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
"earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"},
"ex_doc": {:hex, :ex_doc, "0.29.0", "4a1cb903ce746aceef9c1f9ae8a6c12b742a5461e6959b9d3b24d813ffbea146", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "f096adb8bbca677d35d278223361c7792d496b3fc0d0224c9d4bc2f651af5db1"},
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
"earmark_parser": {:hex, :earmark_parser, "1.4.33", "3c3fd9673bb5dcc9edc28dd90f50c87ce506d1f71b70e3de69aa8154bc695d44", [:mix], [], "hexpm", "2d526833729b59b9fdb85785078697c72ac5e5066350663e5be6a1182da61b8f"},
"ex_doc": {:hex, :ex_doc, "0.30.6", "5f8b54854b240a2b55c9734c4b1d0dd7bdd41f71a095d42a70445c03cf05a281", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bd48f2ddacf4e482c727f9293d9498e0881597eae6ddc3d9562bd7923375109f"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
"rustler": {:hex, :rustler, "0.25.0", "32526b51af7e58a740f61941bf923486ce6415a91c3934cc16c281aa201a2240", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "6b43a11a37fe79c6234d88c4102ab5dfede7a6a764dc5c7b539956cfa02f3cf4"},
"rustler_precompiled": {:hex, :rustler_precompiled, "0.5.4", "34f79a8bdeeb094590b6d88a03469c90d2192c45ac10afcae2acf4f1b925b2dc", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "c5a078315c5f450281f75c0953b14535fbaaad737b85a97a2b72983f45cc30d2"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"},
"nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"},
"rustler": {:hex, :rustler, "0.29.1", "880f20ae3027bd7945def6cea767f5257bc926f33ff50c0d5d5a5315883c084d", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "109497d701861bfcd26eb8f5801fe327a8eef304f56a5b63ef61151ff44ac9b6"},
"rustler_precompiled": {:hex, :rustler_precompiled, "0.6.3", "f838d94bc35e1844973ee7266127b156fdc962e9e8b7ff666c8fb4fed7964d23", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "e18ecca3669a7454b3a2be75ae6c3ef01d550bc9a8cf5fbddcfff843b881d7c6"},
"toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"},
}

0 comments on commit ea81ac6

Please sign in to comment.