diff --git a/message.go b/message.go index 25b78a9..d9411ab 100644 --- a/message.go +++ b/message.go @@ -230,13 +230,27 @@ func (m *Message) Unpack(src []byte) error { m.mu.Lock() defer m.mu.Unlock() - return m.unpack(src) + return m.wrapErrorUnpack(src) +} + +// wrapErrorUnpack calls the core unpacking logic and wraps any +// errors in a *UnpackError. It assumes that the mutex is already +// locked by the caller. +func (m *Message) wrapErrorUnpack(src []byte) error { + if fieldID, err := m.unpack(src); err != nil { + return &UnpackError{ + Err: err, + FieldID: fieldID, + RawMessage: src, + } + } + return nil } // unpack contains the core logic for unpacking the message. This method does // not handle locking or error wrapping and should typically be used internally // after ensuring concurrency safety. -func (m *Message) unpack(src []byte) error { +func (m *Message) unpack(src []byte) (string, error) { var off int // reset fields that were set @@ -247,11 +261,7 @@ func (m *Message) unpack(src []byte) error { read, err := m.fields[mtiIdx].Unpack(src) if err != nil { - return &UnpackError{ - Err: fmt.Errorf("failed to unpack MTI: %w", err), - FieldID: strconv.Itoa(mtiIdx), - RawMessage: src, - } + return strconv.Itoa(mtiIdx), fmt.Errorf("failed to unpack MTI: %w", err) } m.fieldsMap[mtiIdx] = struct{}{} @@ -261,11 +271,7 @@ func (m *Message) unpack(src []byte) error { // unpack Bitmap read, err = m.fields[bitmapIdx].Unpack(src[off:]) if err != nil { - return &UnpackError{ - Err: fmt.Errorf("failed to unpack bitmap: %w", err), - FieldID: strconv.Itoa(bitmapIdx), - RawMessage: src, - } + return strconv.Itoa(bitmapIdx), fmt.Errorf("failed to unpack bitmap: %w", err) } off += read @@ -279,20 +285,12 @@ func (m *Message) unpack(src []byte) error { if m.bitmap().IsSet(i) { fl, ok := m.fields[i] if !ok { - return &UnpackError{ - Err: fmt.Errorf("failed to unpack field %d: no specification found", i), - FieldID: strconv.Itoa(i), - RawMessage: src, - } + return strconv.Itoa(i), fmt.Errorf("failed to unpack field %d: no specification found", i) } read, err = fl.Unpack(src[off:]) if err != nil { - return &UnpackError{ - Err: fmt.Errorf("failed to unpack field %d (%s): %w", i, fl.Spec().Description, err), - FieldID: strconv.Itoa(i), - RawMessage: src, - } + return strconv.Itoa(i), fmt.Errorf("failed to unpack field %d (%s): %w", i, fl.Spec().Description, err) } m.fieldsMap[i] = struct{}{} @@ -301,7 +299,7 @@ func (m *Message) unpack(src []byte) error { } } - return nil + return "", nil } func (m *Message) MarshalJSON() ([]byte, error) {