parse

package
v0.0.0-...-3b7a441 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 26, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package parse provides HL7 v2.x message parsing functionality.

The parse package converts raw HL7 message bytes or strings into structured hl7.Message objects. It handles delimiter detection, segment splitting, field parsing, escape sequence processing, and validation.

Basic Usage

Parse a message from bytes:

p := parse.New()
msg, err := p.Parse(data)
if err != nil {
    log.Fatal("parse error:", err)
}

// Access message data
msgType := msg.Type()         // e.g., "ADT^A01"
controlID := msg.ControlID()  // e.g., "12345"
version := msg.Version()      // e.g., "2.5.1"

Parse a message from a string:

msg, err := p.ParseString(hl7String)
if err != nil {
    log.Fatal("parse error:", err)
}

Parser Options

The parser supports functional options for configuration:

// Enable strict parsing mode
p := parse.New(parse.WithStrictMode(true))

// Allow empty segments
p := parse.New(parse.WithAllowEmptySegments(true))

// Use custom delimiters (for non-standard messages)
delims := &hl7.Delimiters{
    Field:        '|',
    Component:    '^',
    Repetition:   '~',
    Escape:       '\\',
    SubComponent: '&',
}
p := parse.New(parse.WithCustomDelimiters(delims))

// Set DoS protection limits
p := parse.New(
    parse.WithMaxSegments(500),
    parse.WithMaxFieldLength(32768),
)

// Use a different segment terminator (default is CR)
p := parse.New(parse.WithSegmentTerminator('\n'))

Delimiter Detection

By default, the parser automatically detects delimiters from the MSH segment:

  • MSH-1 (position 3) contains the field separator
  • MSH-2 (positions 4-7) contains the encoding characters

For standard HL7 messages, delimiters are typically:

MSH|^~\&|...

Where | is the field separator, ^ is component, ~ is repetition, \ is escape, and & is subcomponent.

Strict Mode

When strict mode is enabled, the parser performs additional validation:

  • Segment names must be exactly 3 uppercase alphanumeric characters
  • MSH segment must be first
  • Required fields in MSH must be present
  • Field lengths are validated against maximums

In non-strict mode (default), the parser is more lenient and will accept messages with minor formatting issues.

DoS Protection

The parser includes built-in protection against denial-of-service attacks:

  • Maximum segment count (default: 1000)
  • Maximum field length (default: 65536 bytes)

These limits prevent maliciously crafted messages from consuming excessive memory or CPU time.

Error Handling

Parse errors include detailed information about what went wrong:

msg, err := p.Parse(data)
if err != nil {
    // Error contains location and description
    fmt.Println("Parse failed:", err)
}

Common error conditions:

  • Missing or invalid MSH segment
  • Invalid delimiters
  • Segment count exceeds maximum
  • Field length exceeds maximum
  • Invalid escape sequences (in strict mode)

Example: Complete Parsing Workflow

// Create parser with options
p := parse.New(
    parse.WithStrictMode(true),
    parse.WithMaxSegments(500),
)

// Parse message
msg, err := p.Parse(rawHL7Data)
if err != nil {
    return fmt.Errorf("failed to parse HL7 message: %w", err)
}

// Extract message metadata
fmt.Printf("Message Type: %s\n", msg.Type())
fmt.Printf("Control ID: %s\n", msg.ControlID())
fmt.Printf("Version: %s\n", msg.Version())

// Access patient data
patientID, _ := msg.Get("PID.3.1")
patientName, _ := msg.Get("PID.5")
dob, _ := msg.Get("PID.7")

fmt.Printf("Patient: %s (ID: %s, DOB: %s)\n",
    patientName, patientID, dob)

// Iterate over observations
for _, obx := range msg.Segments("OBX") {
    obsID, _ := obx.Get("3")
    value, _ := obx.Get("5")
    units, _ := obx.Get("6")
    fmt.Printf("  %s: %s %s\n", obsID, value, units)
}

Package parse provides HL7 v2.x message parsing functionality.

Package parse provides HL7 v2.x message parsing functionality.

Package parse provides HL7 v2.x message parsing functionality.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrTooManySegments is returned when the message exceeds maxSegments.
	ErrTooManySegments = errors.New("message exceeds maximum segment count")
	// ErrFieldTooLong is returned when a field exceeds maxFieldLength.
	ErrFieldTooLong = errors.New("field exceeds maximum length")
	// ErrContextCanceled is returned when the parsing context is canceled.
	ErrContextCanceled = errors.New("parsing canceled")
	// ErrEmptySegment is returned when an empty segment is found and not allowed.
	ErrEmptySegment = errors.New("empty segment not allowed")
)

Parser-specific errors.

View Source
var (
	// ErrMessageTooLarge is returned when a message exceeds the maximum size.
	ErrMessageTooLarge = errors.New("message exceeds maximum size")
)

Scanner-specific errors.

Functions

This section is empty.

Types

type Parser

type Parser interface {
	// Parse parses raw HL7 message data into a Message.
	// The input data may include MLLP framing which will be stripped.
	Parse(data []byte) (hl7.Message, error)

	// ParseContext parses raw HL7 message data with context support.
	// Allows for cancellation during parsing of large messages.
	ParseContext(ctx context.Context, data []byte) (hl7.Message, error)
}

Parser defines the interface for HL7 message parsing.

func New

func New(opts ...ParserOption) Parser

New creates a new Parser with the given options.

type ParserOption

type ParserOption func(*parserConfig)

ParserOption is a functional option for configuring the parser.

func WithAllowEmptySegments

func WithAllowEmptySegments(allow bool) ParserOption

WithAllowEmptySegments configures whether empty segments are allowed. When enabled, segments with no fields (just the segment name) are permitted.

func WithCustomDelimiters

func WithCustomDelimiters(d *hl7.Delimiters) ParserOption

WithCustomDelimiters sets custom delimiters for parsing. When set, the parser will use these delimiters instead of extracting them from the MSH segment. This is useful for parsing non-standard messages or message fragments.

func WithMaxFieldLength

func WithMaxFieldLength(limit int) ParserOption

WithMaxFieldLength sets the maximum field length allowed. This is a DoS protection mechanism to prevent processing of messages with excessively large fields. Default is 65536 bytes.

func WithMaxSegments

func WithMaxSegments(limit int) ParserOption

WithMaxSegments sets the maximum number of segments allowed in a message. This is a DoS protection mechanism to prevent processing of maliciously large messages. Default is 1000.

func WithSegmentTerminator

func WithSegmentTerminator(term rune) ParserOption

WithSegmentTerminator sets the segment terminator character. The default is carriage return (CR, 0x0D) as per HL7 standard. Some implementations use line feed (LF, 0x0A) or other characters.

func WithStrictMode

func WithStrictMode(strict bool) ParserOption

WithStrictMode enables or disables strict parsing mode. In strict mode, the parser is more rigorous about HL7 compliance and will reject messages with minor formatting issues.

type Scanner

type Scanner interface {
	// Scan advances to the next message. Returns true if a message was found.
	Scan() bool

	// Message returns the last parsed message.
	// Returns nil if Scan hasn't been called or returned false.
	Message() hl7.Message

	// Err returns any error encountered during scanning.
	// Returns nil if no error occurred.
	Err() error
}

Scanner provides streaming HL7 message parsing from an io.Reader. It supports both MLLP-framed messages and plain CR-delimited messages.

Example (MultipleMessages)
// Stream containing multiple HL7 messages
input := "MSH|^~\\&|APP|FAC|||2023||ADT|MSG1|P|2.5\rPID|1||12345\r\r" +
	"MSH|^~\\&|APP|FAC|||2023||ORU|MSG2|P|2.5\rOBX|1|NM|WBC||7.5\r"

r := strings.NewReader(input)
scanner := NewScanner(r)

messages := []hl7.Message{}
for scanner.Scan() {
	messages = append(messages, scanner.Message())
}

// messages now contains both parsed messages
_ = messages

func NewScanner

func NewScanner(r io.Reader, opts ...ParserOption) Scanner

NewScanner creates a new Scanner that reads from the given io.Reader. The scanner will parse messages using the provided ParserOptions.

Example

Example tests

input := "MSH|^~\\&|SEND|FAC|||2023||ADT^A01|MSG001|P|2.5\rPID|1||12345\r"
r := strings.NewReader(input)

scanner := NewScanner(r)
for scanner.Scan() {
	msg := scanner.Message()
	_ = msg // Process message
}

if err := scanner.Err(); err != nil {
	_ = err // Handle error in real code
}

func NewScannerWithOptions

func NewScannerWithOptions(r io.Reader, parserOpts []ParserOption, scannerOpts ...ScannerOption) Scanner

NewScannerWithOptions creates a new Scanner with additional scanner-specific options.

type ScannerOption

type ScannerOption func(*scanner)

ScannerOption is a functional option for configuring the scanner.

func WithMaxMessageSize

func WithMaxMessageSize(size int) ScannerOption

WithMaxMessageSize sets the maximum allowed message size in bytes. Default is 10 MB.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL