Current section

Files

Jump to
elixir_hl7 lib hl7 mllp_stream.ex
Raw

lib/hl7/mllp_stream.ex

defmodule HL7.MLLPStream do
@moduledoc false
require Logger
# ^K - VT (Vertical Tab) - 0x0B
@sb "\v"
# ^\ - FS (File Separator)
@eb <<0x1C>>
# ^M - CR (Carriage Return) - 0x0D
@cr "\r"
@ending @eb <> @cr
@spec get_prefix() :: String.t()
def get_prefix() do
@sb
end
@spec get_suffix() :: String.t()
def get_suffix() do
@ending
end
@spec raw_to_messages(Enumerable.t()) :: Enumerable.t()
def raw_to_messages(input_stream) do
Stream.chunk_while(input_stream, "", &chunker/2, &after_chunking/1) |> Stream.concat()
end
@spec after_sb(String.t()) :: nil | String.t()
defp after_sb(text) do
chunks = text |> String.split(@sb, parts: 2)
case chunks do
[_chunk] -> nil
[_sb, msg] -> msg
end
end
@spec to_list_and_remnant(list()) :: {:cont, list(), String.t()}
defp to_list_and_remnant(potential_messages) do
[remnant | reverse_msgs] = potential_messages |> Enum.reverse()
msgs =
reverse_msgs
|> Enum.map(&after_sb(&1))
|> Enum.filter(fn m -> is_binary(m) and m != "" end)
|> Enum.reverse()
{:cont, msgs, remnant}
end
@spec chunker(String.t(), String.t()) :: {:cont, String.t()} | {:cont, list(), String.t()}
defp chunker(element, acc) when is_binary(element) do
# {:cont, chunk, acc} | {:cont, acc} | {:halt, acc})
text = acc <> element
potential_msg_list = String.split(text, @ending)
case potential_msg_list do
[not_found] -> {:cont, not_found}
_ -> potential_msg_list |> to_list_and_remnant
end
end
@spec after_chunking(any()) :: {:cont, []}
defp after_chunking(_acc) do
{:cont, []}
end
end