defmodule HL7 do
@moduledoc """
Utility functions to load HL7 files as local streams.
"""
require Logger
@buffer_size 32768
@type file_type_hl7 :: :mllp | :line | nil
@doc """
Opens an HL7 file stream of either `:mllp`, `:smat` or `:line`. If the file_type is not specified
it will be inferred from the first three characters of the file contents.
"""
@spec open_hl7_file_stream(String.t(), file_type_hl7()) :: Enumerable.t()
def open_hl7_file_stream(file_path, file_type \\ nil) when is_atom(file_type) do
found_file_type =
file_type
|> case do
nil ->
infer_file_type(file_path)
_ ->
if File.exists?(file_path) do
{:ok, file_type}
else
{:error, :enoent}
end
end
found_file_type
|> case do
{:ok, :line} ->
file_path
|> File.stream!([], @buffer_size)
{:ok, :mllp} ->
file_path
|> File.stream!([], @buffer_size)
|> HL7.MLLPStream.raw_to_messages()
{:error, reason} ->
{:error, reason}
end
end
@spec infer_file_type(String.t()) :: {:ok, :line} | {:ok, :mllp} | {:error, atom()}
defp infer_file_type(file_path) do
File.open(file_path, [:read])
|> case do
{:ok, file_ref} ->
first_three = IO.binread(file_ref, 3)
_ = File.close(file_ref)
case first_three do
<<"MSH">> ->
{:ok, :line}
<<0x0B, "M", "S">> ->
{:ok, :mllp}
_ ->
{:error, :unrecognized_file_type}
end
error ->
error
end
end
end