lib/exampple/xml/stream.ex

defmodule Exampple.Xml.Stream do
  @moduledoc """
  Process a stream chunk by chunk to obtain a XML document.
  The stream is initiated passing a PID where the information
  from the chunks are going to be received.

  The parser is using `Exampple.Xml.Parser.Sender` which is
  responsible to convert the stream data into a valid `%Xmlel{}`
  and send it back to the specified process.
  """

  alias Saxy.Partial

  @handler Exampple.Xml.Parser.Sender

  @doc """
  Creates a new `Saxy.Partial` struct to parser little by little
  the incoming stream. The information is sent back to the `pid`
  passed as a paramter, by default this is set as `self()`.
  """
  def new(pid \\ self()) do
    {:ok, partial} = Partial.new(@handler, pid)
    partial
  end

  @doc """
  Use it to send every chunk of the XML document(s) we want to
  parse. Every `chunk` will be sent back to the process passed
  initially in the new function through the `partial` parameter.
  """
  def parse({:cont, partial}, chunk), do: parse(partial, chunk)

  def parse({:halt, pid, rest}, chunk) do
    pid
    |> new()
    |> parse(rest <> chunk)
  end

  def parse(partial, chunk) do
    Partial.parse(partial, chunk)
  end

  @doc """
  When we wants to send the rest of the XML document(s) we
  have to use this function which let us to finalise the
  `partial` data.
  """
  def terminate({:cont, partial}), do: terminate(partial)

  def terminate({:halt, _state, rest}) do
    {:ok, rest}
  end

  def terminate(partial) do
    {:ok, _state} = Partial.terminate(partial)
    {:ok, ""}
  end
end