hl7

package module
v0.0.0-...-1f0d292 Latest Latest
Warning

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

Go to latest
Published: May 24, 2024 License: MIT Imports: 10 Imported by: 0

README

HL7

Test

This is a basic HL7 parser written in Go. There are no external dependencies, only the standard library is used for runtime code (github.com/testify/assert is used in tests to make them easier to reason about).

This parser accepts an io.Reader as the input, so anything that follows that interface should be usable here, such as files and TCP streams. Note that this does not currently support MLLP.

This library is tested to work on the following platforms:

  • Go versions 1.16.x, 1.17.x, and 1.18.x
  • Latest version of macOS (AMD64)
  • Latest version of Windows (AMD64)
  • Latest version of Ubuntu (AMD64)

It should probably work without issue in older versions of Go and operating systems since we are not utilizing any low-level features or anything particularly modern in Go.

Installation

Installation is simple:

$ go get github.com/ldmtam/hl7

Usage

Usage is meant to mimic the semantics of a reader. Additionally, the HL7 data is read from an io.Reader, so it's relatively trivial to read HL7 data from a variety of sources (a file, TCP connection, bytes.Buffer, etc.). Actual parsing of the message happens when you fetch a segment. This laziness should help with large messages, particularly when you find out halfway through the message that you don't care about it anymore (maybe it doesn't have anything to do with your business case).

For example usage, see the example program. There is an example file with HL7 data in it gathered from Wikipedia and Ringholm bv.

Further usage information can be found here.

TODO

I would like to add the following functionality, but it's not on the immediate schedule:

  • A way to handle unmarshalling using Go semantics (struct tags, etc.).
  • Some validation of the input data (this isn't likely; it means this program will need to know a lot about HL7 and I might not have time to implement it correctly).
  • MLLP

Documentation

Index

Constants

View Source
const (
	CR = '\r'   // Carriage return
	LF = '\n'   // Line feed
	FF = '\f'   // Form feed
	NB = '\x00' // Null byte
)

Constants describing possible message boundaries.

Variables

View Source
var ErrUnknownTimeFormat = errors.New("unknown time format")

ErrUnknownTimeFormat is used to represent the case where the time format encountered in the HL7 file is unknown. Maybe we don't know how to parse it yet, or maybe the HL7 file is not complying with the spec?

Functions

func FormatString

func FormatString(str string) string

FormatString is used to perform basic HL7 formatting rules on the string. This function does not aim to have 100% coverage of the HL7 formatted text spec since a lot of those rules do not seem to be widely used. This does aim to address the common and easy cases, though.

Types

type Component

type Component []SubComponent

Component is used to represent a slice of sub-components.

func (Component) GetSubComponent

func (c Component) GetSubComponent(idx int) (SubComponent, bool)

GetSubComponent is used to get the sub-component at the given index.

type Field

type Field []Component

Field is a slice of components.

func (Field) GetComponent

func (f Field) GetComponent(idx int) (Component, bool)

GetComponent is used to get the component at the given index.

func (Field) GetSubComponent

func (f Field) GetSubComponent(compIdx, subCompIdx int) (SubComponent, bool)

GetSubComponent is used to get the sub-component at the given index.

type Fields

type Fields []Field

Fields is a slice of fields

func (Fields) GetComponent

func (f Fields) GetComponent(fieldIdx, compIdx int) (Component, bool)

GetComponent is used to get the component at the given index.

func (Fields) GetField

func (f Fields) GetField(idx int) (Field, bool)

GetField is used to get the field at the given index.

func (Fields) GetSubComponent

func (f Fields) GetSubComponent(fieldIdx, compIdx, subCompIdx int) (SubComponent, bool)

GetSubComponent is used to get the component at the given index.

type Message

type Message struct {
	// contains filtered or unexported fields
}

Message is used to describe the parsed message.

func NewMessage

func NewMessage(data []byte) (*Message, error)

NewMessage takes a byte slice and returns a Message that is ready to use.

func (*Message) Parse

func (m *Message) Parse() (map[string][]Segment, error)

Parse is used to parse the segments within the message so that they can be queried and iterated. This is a different paradigm from the ReadSegment method, which parses the segments as-needed.

func (*Message) ReadSegment

func (m *Message) ReadSegment() (Segment, error)

ReadSegment is used to "read" the next segment from the message.

type MessageFunc

type MessageFunc func(msg *Message) error

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader is the type used to read messages from an internal bufio.Reader.

func NewReader

func NewReader(reader io.Reader) *Reader

NewReader is used to return a new Reader that is ready to use.

func (*Reader) EachMessage

func (r *Reader) EachMessage(fn MessageFunc) error

EachMessage is used to create a bit of a friendlier API for reading messages if all you're doing is (for example) importing the messages' data into a database or something. Each message is passed into the MessageFunc provided and executed in order. The downside of this implementation is that it will not happen concurrently, which could have some performance ramifications.

Errors returned from this will not include io.EOF, so when you're done processing the work, only "real" errors are returned here, such as errors parsing the HL7 data and errors reading from the input io.Reader.

func (*Reader) ReadMessage

func (r *Reader) ReadMessage() (*Message, error)

ReadMessage is used to read the next message in the internal reader.

If the reader is empty (or at io.EOF), io.EOF is returned with an empty message. Otherwise, error will always be nil.

type Segment

type Segment []Fields

Segment is a slice of fields.

func (Segment) GetComponent

func (s Segment) GetComponent(fieldsIdx, fieldIdx, compIdx int) (Component, bool)

GetComponent is used to get the component at the given index

func (Segment) GetField

func (s Segment) GetField(fieldsIdx, fieldIdx int) (Field, bool)

GetField is used to get the field at the given index

func (Segment) GetFields

func (s Segment) GetFields(idx int) (Fields, bool)

GetFields is used to get the fields at the given index

func (Segment) GetSubComponent

func (s Segment) GetSubComponent(fieldsIdx, fieldIdx, compIdx, subCompIdx int) (SubComponent, bool)

GetSubComponent is used to get the sub-component at the given index

func (Segment) Type

func (s Segment) Type() string

Type is used to return the type of segment this is.

type SubComponent

type SubComponent []byte

SubComponent is the basic unit in HL7s. This is not strictly standards- compliant, since not all fields have sub-components but it is close enough.

func (SubComponent) DirtyString

func (s SubComponent) DirtyString() string

DirtyString is the string value value without any escaping performed.

func (SubComponent) Int

func (s SubComponent) Int() (int, error)

Int is used to return an integer value housed in a SubComponent.

func (SubComponent) String

func (s SubComponent) String() string

String is used to return the string value housed in a SubComponent. We convert HL7 escape codes, linebreaks, etc. into standard values.

func (SubComponent) Time

func (s SubComponent) Time() (time.Time, error)

Time is used to return a date value housed in a SubComponent.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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