Packages
hl7v2
2.3.0
3.10.1
3.9.0
3.8.0
3.7.0
3.6.0
3.5.0
3.4.0
3.3.6
3.3.5
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.0
3.1.1
3.1.0
3.0.2
3.0.1
3.0.0
2.11.0
2.10.0
2.9.1
2.9.0
2.8.2
2.8.1
2.8.0
2.7.1
2.7.0
2.6.0
2.5.0
2.4.0
2.3.0
2.2.0
2.1.3
2.1.2
2.1.1
2.1.0
1.4.6
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.0
1.1.0
1.0.0
0.6.0
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.1.0
Pure Elixir HL7 v2.x toolkit — schema-driven parsing, typed segments, message builder, MLLP transport
Current section
Files
Jump to
Current section
Files
lib/hl7v2/segment/msh.ex
defmodule HL7v2.Segment.MSH do
@moduledoc """
Message Header (MSH) segment — HL7v2 v2.5.1.
The first segment of every HL7v2 message. MSH-1 and MSH-2 receive special
treatment: MSH-1 is the field separator character itself, and MSH-2 is the
encoding characters literal string.
21 fields per HL7 v2.5.1 specification.
"""
use HL7v2.Segment,
id: "MSH",
fields: [
{1, :field_separator, HL7v2.Type.ST, :r, 1},
{2, :encoding_characters, HL7v2.Type.ST, :r, 1},
{3, :sending_application, HL7v2.Type.HD, :o, 1},
{4, :sending_facility, HL7v2.Type.HD, :o, 1},
{5, :receiving_application, HL7v2.Type.HD, :o, 1},
{6, :receiving_facility, HL7v2.Type.HD, :o, 1},
{7, :date_time_of_message, HL7v2.Type.TS, :r, 1},
{8, :security, HL7v2.Type.ST, :o, 1},
{9, :message_type, HL7v2.Type.MSG, :r, 1},
{10, :message_control_id, HL7v2.Type.ST, :r, 1},
{11, :processing_id, HL7v2.Type.PT, :r, 1},
{12, :version_id, HL7v2.Type.VID, :r, 1},
{13, :sequence_number, HL7v2.Type.NM, :o, 1},
{14, :continuation_pointer, HL7v2.Type.ST, :o, 1},
{15, :accept_acknowledgment_type, HL7v2.Type.ID, :o, 1},
{16, :application_acknowledgment_type, HL7v2.Type.ID, :o, 1},
{17, :country_code, HL7v2.Type.ID, :o, 1},
{18, :character_set, HL7v2.Type.ID, :o, :unbounded},
{19, :principal_language_of_message, HL7v2.Type.CE, :o, 1},
{20, :alternate_character_set_handling_scheme, HL7v2.Type.ID, :o, 1},
{21, :message_profile_identifier, HL7v2.Type.EI, :o, :unbounded}
]
@doc """
Parses MSH with special handling for MSH-1 (field separator) and MSH-2
(encoding characters), which are stored as-is rather than type-parsed.
"""
@impl HL7v2.Segment
@spec parse(list(), HL7v2.Separator.t()) :: t()
def parse(raw_fields, separators \\ HL7v2.Separator.default()) do
sep = <<separators.sub_component>>
ensure_sep = fn fun ->
if Process.get(:hl7v2_sub_component_sep) do
fun.()
else
HL7v2.Type.with_sub_component_separator(sep, fun)
end
end
ensure_sep.(fn ->
# MSH-1 and MSH-2 are special: store as literal strings
base = %__MODULE__{
field_separator: Enum.at(raw_fields, 0),
encoding_characters: Enum.at(raw_fields, 1)
}
# Parse remaining fields (MSH-3 onwards) using standard logic
remaining_fields = Enum.drop(@segment_fields, 2)
attrs =
Enum.map(remaining_fields, fn {seq, name, type, _opt, max_reps} ->
raw = Enum.at(raw_fields, seq - 1)
{name, HL7v2.Segment.parse_field_value(raw, type, max_reps)}
end)
max_seq = HL7v2.Segment.max_declared_seq(@segment_fields)
extra = Enum.drop(raw_fields, max_seq)
struct(base, [{:extra_fields, extra} | attrs])
end)
end
@doc """
Encodes MSH with special handling for MSH-1 and MSH-2.
"""
@impl HL7v2.Segment
@spec encode(t()) :: list()
def encode(%__MODULE__{} = msh) do
remaining_fields = Enum.drop(@segment_fields, 2)
rest =
Enum.map(remaining_fields, fn {_seq, name, type, _opt, max_reps} ->
value = Map.get(msh, name)
HL7v2.Segment.encode_field_value(value, type, max_reps)
end)
extra = msh.extra_fields || []
[msh.field_separator, msh.encoding_characters | HL7v2.Segment.trim_trailing(rest ++ extra)]
end
end