From de9bb7d63d8f47aa5dff2a25a2b73723802a9462 Mon Sep 17 00:00:00 2001 From: Pavel Gabriel Date: Fri, 1 Aug 2025 16:47:41 +0200 Subject: [PATCH] wrap error into prefix.LengthError type --- field/binary_test.go | 3 ++- field/composite_test.go | 19 +++++++++++++------ field/hex_test.go | 3 ++- field/numeric_test.go | 3 ++- field/string_test.go | 3 ++- prefix/ascii.go | 24 ++++++++++++++++++------ prefix/ascii_test.go | 8 ++++++-- prefix/bcd.go | 20 +++++++++++++++----- prefix/bcd_test.go | 11 ++++++++--- prefix/bertlv.go | 12 +++++++++--- prefix/bertlv_test.go | 6 ++++-- prefix/binary.go | 24 ++++++++++++++++++------ prefix/ebcdic.go | 20 +++++++++++++++----- prefix/ebcdic1047.go | 20 +++++++++++++++----- prefix/ebcdic1047_test.go | 13 ++++++++----- prefix/ebcdic_test.go | 11 ++++++++--- prefix/error.go | 25 +++++++++++++++++++++++-- prefix/hex.go | 24 ++++++++++++++++++------ 18 files changed, 186 insertions(+), 63 deletions(-) diff --git a/field/binary_test.go b/field/binary_test.go index 227de551..7ade682c 100644 --- a/field/binary_test.go +++ b/field/binary_test.go @@ -123,7 +123,8 @@ func TestBinaryField(t *testing.T) { bin := NewBinary(spec) _, err := bin.Pack() - require.EqualError(t, err, "failed to encode length: field length: 0 should be fixed: 10") + require.EqualError(t, err, "failed to encode length: data length: 0 should be fixed: 10") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) } diff --git a/field/composite_test.go b/field/composite_test.go index 8e4b146f..29e432ea 100644 --- a/field/composite_test.go +++ b/field/composite_test.go @@ -757,7 +757,8 @@ func TestCompositePacking(t *testing.T) { require.NoError(t, err) _, err = composite.Pack() - require.EqualError(t, err, "failed to pack subfield 1: failed to encode length: field length: 4 should be fixed: 2") + require.EqualError(t, err, "failed to pack subfield 1: failed to encode length: data length: 4 should be fixed: 2") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) t.Run("Pack returns error when encoded data length is larger than specified fixed max length", func(t *testing.T) { @@ -798,7 +799,8 @@ func TestCompositePacking(t *testing.T) { require.NoError(t, err) _, err = composite.Pack() - require.EqualError(t, err, "failed to encode length: field length: 6 should be fixed: 4") + require.EqualError(t, err, "failed to encode length: data length: 6 should be fixed: 4") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) t.Run("Pack correctly serializes data with padded tags to bytes", func(t *testing.T) { @@ -948,6 +950,7 @@ func TestCompositePacking(t *testing.T) { require.Equal(t, 0, read) require.Error(t, err) require.EqualError(t, err, "failed to decode length: data length: 7 is larger than maximum 4") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) t.Run("Unpack without error when not all subfields are set", func(t *testing.T) { @@ -1100,7 +1103,8 @@ func TestCompositePackingWithTags(t *testing.T) { b, err := composite.Pack() require.Nil(t, b) require.Error(t, err) - require.EqualError(t, err, "failed to encode length: field length: 12 should be fixed: 6") + require.EqualError(t, err, "failed to encode length: data length: 12 should be fixed: 6") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) t.Run("Pack returns error when encoded data length is larger than specified variable max length", func(t *testing.T) { @@ -1143,7 +1147,8 @@ func TestCompositePackingWithTags(t *testing.T) { b, err := composite.Pack() require.Nil(t, b) - require.EqualError(t, err, "failed to encode length: field length: 12 is larger than maximum: 8") + require.EqualError(t, err, "failed to encode length: data length: 12 is larger than maximum: 8") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) t.Run("Pack correctly serializes fully populated data to bytes", func(t *testing.T) { @@ -1352,7 +1357,8 @@ func TestCompositePackingWithBitmap(t *testing.T) { b, err := composite.Pack() require.Nil(t, b) require.Error(t, err) - require.EqualError(t, err, "failed to encode length: field length: 14 should be fixed: 20") + require.EqualError(t, err, "failed to encode length: data length: 14 should be fixed: 20") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) t.Run("Pack returns error when encoded data length is larger than specified variable max length", func(t *testing.T) { @@ -1395,7 +1401,8 @@ func TestCompositePackingWithBitmap(t *testing.T) { b, err := composite.Pack() require.Nil(t, b) - require.EqualError(t, err, "failed to encode length: field length: 14 is larger than maximum: 5") + require.EqualError(t, err, "failed to encode length: data length: 14 is larger than maximum: 5") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) t.Run("Pack correctly serializes fully populated data to bytes with default bitmap", func(t *testing.T) { diff --git a/field/hex_test.go b/field/hex_test.go index 5ae3b6b7..38199dea 100644 --- a/field/hex_test.go +++ b/field/hex_test.go @@ -165,7 +165,8 @@ func TestHexPack(t *testing.T) { str := NewHex(spec) _, err := str.Pack() - require.EqualError(t, err, "failed to encode length: field length: 0 should be fixed: 10") + require.EqualError(t, err, "failed to encode length: data length: 0 should be fixed: 10") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) } diff --git a/field/numeric_test.go b/field/numeric_test.go index 82679257..f90e2a63 100644 --- a/field/numeric_test.go +++ b/field/numeric_test.go @@ -84,7 +84,8 @@ func TestNumericPack(t *testing.T) { _, err := numeric.Pack() // zero value for Numeric is 0, so we have default field length 1 - require.EqualError(t, err, "failed to encode length: field length: 1 should be fixed: 10") + require.EqualError(t, err, "failed to encode length: data length: 1 should be fixed: 10") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) } diff --git a/field/string_test.go b/field/string_test.go index 513cfd5f..2194da8c 100644 --- a/field/string_test.go +++ b/field/string_test.go @@ -85,7 +85,8 @@ func TestStringPack(t *testing.T) { str := NewString(spec) _, err := str.Pack() - require.EqualError(t, err, "failed to encode length: field length: 0 should be fixed: 10") + require.EqualError(t, err, "failed to encode length: data length: 0 should be fixed: 10") + require.True(t, prefix.IsLengthError(err), "error should be a length error") }) } diff --git a/prefix/ascii.go b/prefix/ascii.go index b6bb3c94..421fc76c 100644 --- a/prefix/ascii.go +++ b/prefix/ascii.go @@ -22,11 +22,15 @@ var ASCII = Prefixers{ func (p *asciiVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { if dataLen > maxLen { - return nil, fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen), + } } if len(strconv.Itoa(dataLen)) > p.Digits { - return nil, fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits) + return nil, &LengthError{ + fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits), + } } res := fmt.Sprintf("%0*d", p.Digits, dataLen) @@ -36,7 +40,9 @@ func (p *asciiVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { func (p *asciiVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, error) { if len(data) < p.Digits { - return 0, 0, fmt.Errorf(notEnoughDataToRead, len(data), p.Digits) + return 0, 0, &LengthError{ + fmt.Errorf(notEnoughDataToRead, len(data), p.Digits), + } } dataLen, err := strconv.Atoi(string(data[:p.Digits])) @@ -46,11 +52,15 @@ func (p *asciiVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, erro // length should be positive if dataLen < 0 { - return 0, 0, fmt.Errorf(invalidLength, dataLen) + return 0, 0, &LengthError{ + fmt.Errorf(invalidLength, dataLen), + } } if dataLen > maxLen { - return 0, 0, fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen) + return 0, 0, &LengthError{ + fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen), + } } return dataLen, p.Digits, nil @@ -65,7 +75,9 @@ type asciiFixedPrefixer struct { func (p *asciiFixedPrefixer) EncodeLength(fixLen, dataLen int) ([]byte, error) { if dataLen != fixLen { - return nil, fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen), + } } return []byte{}, nil diff --git a/prefix/ascii_test.go b/prefix/ascii_test.go index ec290f08..88bafe7f 100644 --- a/prefix/ascii_test.go +++ b/prefix/ascii_test.go @@ -14,6 +14,7 @@ func TestAsciiVarPrefixer_EncodeLengthDigitsValidation(t *testing.T) { _, err := pref.EncodeLength(999, 123) require.Contains(t, err.Error(), "number of digits in length: 123 exceeds: 2") + require.True(t, IsLengthError(err), "error should be a length error") } func TestAsciiVarPrefixer_EncodeLengthMaxLengthValidation(t *testing.T) { @@ -23,7 +24,8 @@ func TestAsciiVarPrefixer_EncodeLengthMaxLengthValidation(t *testing.T) { _, err := pref.EncodeLength(20, 22) - require.Contains(t, err.Error(), "field length: 22 is larger than maximum: 20") + require.Contains(t, err.Error(), "data length: 22 is larger than maximum: 20") + require.True(t, IsLengthError(err), "error should be a length error") } func TestAsciiVarPrefixer_DecodeLengthMaxLengthValidation(t *testing.T) { @@ -34,6 +36,7 @@ func TestAsciiVarPrefixer_DecodeLengthMaxLengthValidation(t *testing.T) { _, _, err := pref.DecodeLength(20, []byte("22")) require.Contains(t, err.Error(), "not enough data length: 2 to read: 3 byte digits") + require.True(t, IsLengthError(err), "error should be a length error") } func TestAsciiVarPrefixer_LHelpers(t *testing.T) { @@ -96,5 +99,6 @@ func TestAsciiFixedPrefixer_EncodeLengthValidation(t *testing.T) { _, err := pref.EncodeLength(8, 12) - require.Contains(t, err.Error(), "field length: 12 should be fixed: 8") + require.Contains(t, err.Error(), "data length: 12 should be fixed: 8") + require.True(t, IsLengthError(err), "error should be a length error") } diff --git a/prefix/bcd.go b/prefix/bcd.go index 03210ff5..68ac94d7 100644 --- a/prefix/bcd.go +++ b/prefix/bcd.go @@ -25,11 +25,15 @@ var BCD = Prefixers{ func (p *bcdVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { if dataLen > maxLen { - return nil, fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen), + } } if len(strconv.Itoa(dataLen)) > p.Digits { - return nil, fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits) + return nil, &LengthError{ + fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits), + } } strLen := fmt.Sprintf("%0*d", p.Digits, dataLen) @@ -44,7 +48,9 @@ func (p *bcdVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { func (p *bcdVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, error) { length := bcd.EncodedLen(p.Digits) if len(data) < length { - return 0, 0, fmt.Errorf(notEnoughDataToRead, length, len(data)) + return 0, 0, &LengthError{ + fmt.Errorf(notEnoughDataToRead, length, len(data)), + } } bDigits, _, err := encoding.BCD.Decode(data[:length], p.Digits) @@ -58,7 +64,9 @@ func (p *bcdVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, error) } if dataLen > maxLen { - return 0, 0, fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen) + return 0, 0, &LengthError{ + fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen), + } } return dataLen, length, nil @@ -73,7 +81,9 @@ type bcdFixedPrefixer struct { func (p *bcdFixedPrefixer) EncodeLength(fixLen, dataLen int) ([]byte, error) { if dataLen != fixLen { - return nil, fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen), + } } return []byte{}, nil diff --git a/prefix/bcd_test.go b/prefix/bcd_test.go index 7ca05711..14508ed4 100644 --- a/prefix/bcd_test.go +++ b/prefix/bcd_test.go @@ -10,18 +10,21 @@ func TestBCDVarPrefixer_EncodeLengthDigitsValidation(t *testing.T) { _, err := BCD.LL.EncodeLength(999, 123) require.Contains(t, err.Error(), "number of digits in length: 123 exceeds: 2") + require.True(t, IsLengthError(err), "error should be a length error") } func TestBCDVarPrefixer_EncodeLengthMaxLengthValidation(t *testing.T) { _, err := BCD.LL.EncodeLength(20, 22) - require.Contains(t, err.Error(), "field length: 22 is larger than maximum: 20") + require.Contains(t, err.Error(), "data length: 22 is larger than maximum: 20") + require.True(t, IsLengthError(err), "error should be a length error") } func TestBCDVarPrefixer_DecodeLengthMaxLengthValidation(t *testing.T) { _, _, err := BCD.LLL.DecodeLength(20, []byte{0x22}) require.Contains(t, err.Error(), "not enough data length: 2 to read: 1 byte digits") + require.True(t, IsLengthError(err), "error should be a length error") } func TestBCDVarPrefixer_LHelpers(t *testing.T) { @@ -85,10 +88,12 @@ func TestBCDFixedPrefixer_EncodeLengthValidation(t *testing.T) { _, err := pref.EncodeLength(8, 12) require.Error(t, err) - require.Contains(t, err.Error(), "field length: 12 should be fixed: 8") + require.Contains(t, err.Error(), "data length: 12 should be fixed: 8") + require.True(t, IsLengthError(err), "error should be a length error") _, err = pref.EncodeLength(8, 6) require.Error(t, err) - require.Contains(t, err.Error(), "field length: 6 should be fixed: 8") + require.Contains(t, err.Error(), "data length: 6 should be fixed: 8") + require.True(t, IsLengthError(err), "error should be a length error") } diff --git a/prefix/bertlv.go b/prefix/bertlv.go index b007c63f..05a76816 100644 --- a/prefix/bertlv.go +++ b/prefix/bertlv.go @@ -36,7 +36,9 @@ func (p *berTLVPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { // checking maxLen for a 0 is a way to disable check and also support // backwards compatibility with the old contract that didn't have maxLen if maxLen != 0 && dataLen > maxLen { - return nil, fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen), + } } buf := big.NewInt(int64(dataLen)).Bytes() @@ -74,7 +76,9 @@ func (p *berTLVPrefixer) DecodeLength(maxLen int, data []byte) (int, int, error) // checking maxLen for a 0 is a way to disable check and also support // backwards compatibility with the old contract that didn't have maxLen if maxLen != 0 && dataLen > maxLen { - return 0, read, fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen) + return 0, read, &LengthError{ + fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen), + } } return dataLen, read, nil @@ -92,7 +96,9 @@ func (p *berTLVPrefixer) DecodeLength(maxLen int, data []byte) (int, int, error) // checking maxLen for a 0 is a way to disable check and also support // backwards compatibility with the old contract that didn't have maxLen if maxLen != 0 && dataLen > maxLen { - return 0, read, fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen) + return 0, read, &LengthError{ + fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen), + } } return dataLen, read, nil diff --git a/prefix/bertlv_test.go b/prefix/bertlv_test.go index b889cc7a..5cbf2455 100644 --- a/prefix/bertlv_test.go +++ b/prefix/bertlv_test.go @@ -39,12 +39,14 @@ func TestBerTLVPrefixer(t *testing.T) { t.Run("when maxLen is set EncodeLength returns error if length is larger than maxLen", func(t *testing.T) { _, err := BerTLV.EncodeLength(2, 3) - require.EqualError(t, err, "field length: 3 is larger than maximum: 2") + require.EqualError(t, err, "data length: 3 is larger than maximum: 2") + require.True(t, IsLengthError(err), "error should be a length error") }) t.Run("when maxLen is set DecodeLength returns error if length is larger than maxLen", func(t *testing.T) { _, _, err := BerTLV.DecodeLength(2, []byte{0b10000010, 0b11111110, 0b00001111}) - require.EqualError(t, err, "field length: 65039 is larger than maximum: 2") + require.EqualError(t, err, "data length: 65039 is larger than maximum: 2") + require.True(t, IsLengthError(err), "error should be a length error") }) } diff --git a/prefix/binary.go b/prefix/binary.go index c3e1e6f0..7bed6c85 100644 --- a/prefix/binary.go +++ b/prefix/binary.go @@ -23,7 +23,9 @@ type binaryFixedPrefixer struct { func (p *binaryFixedPrefixer) EncodeLength(fixLen, dataLen int) ([]byte, error) { if dataLen != fixLen { - return nil, fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen), + } } return []byte{}, nil @@ -71,7 +73,9 @@ func bytesToInt(b []byte) (int, error) { func (p *binaryVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { if dataLen > maxLen { - return nil, fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen), + } } res, err := intToBytes(dataLen) @@ -83,7 +87,9 @@ func (p *binaryVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { res = bytes.TrimLeft(res, "\x00") if len(res) > p.Digits { - return nil, fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits) + return nil, &LengthError{ + fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits), + } } // if len of res is less than p.Digits prepend with 0x00 @@ -99,7 +105,9 @@ func (p *binaryVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { // and the number of bytes read. func (p *binaryVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, error) { if len(data) < p.Digits { - return 0, 0, fmt.Errorf(notEnoughDataToRead, len(data), p.Digits) + return 0, 0, &LengthError{ + fmt.Errorf(notEnoughDataToRead, len(data), p.Digits), + } } prefBytes := data[:p.Digits] @@ -114,11 +122,15 @@ func (p *binaryVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, err dataLen, err := bytesToInt(prefBytes) if err != nil { - return 0, 0, fmt.Errorf("decode length: %w", err) + return 0, 0, &LengthError{ + fmt.Errorf("decode length: %w", err), + } } if dataLen > maxLen { - return 0, 0, fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen) + return 0, 0, &LengthError{ + fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen), + } } return dataLen, p.Digits, nil diff --git a/prefix/ebcdic.go b/prefix/ebcdic.go index dad9e395..4a9118b0 100644 --- a/prefix/ebcdic.go +++ b/prefix/ebcdic.go @@ -24,11 +24,15 @@ var EBCDIC = Prefixers{ func (p *ebcdicVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { if dataLen > maxLen { - return nil, fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen), + } } if len(strconv.Itoa(dataLen)) > p.Digits { - return nil, fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits) + return nil, &LengthError{ + fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits), + } } strLen := fmt.Sprintf("%0*d", p.Digits, dataLen) @@ -43,7 +47,9 @@ func (p *ebcdicVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { func (p *ebcdicVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, error) { length := p.Digits if len(data) < length { - return 0, 0, fmt.Errorf(notEnoughDataToRead, length, len(data)) + return 0, 0, &LengthError{ + fmt.Errorf(notEnoughDataToRead, length, len(data)), + } } bDigits, _, err := encoding.EBCDIC.Decode(data[:length], p.Digits) @@ -57,7 +63,9 @@ func (p *ebcdicVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, err } if dataLen > maxLen { - return 0, 0, fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen) + return 0, 0, &LengthError{ + fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen), + } } return dataLen, length, nil @@ -72,7 +80,9 @@ type ebcdicFixedPrefixer struct { func (p *ebcdicFixedPrefixer) EncodeLength(fixLen, dataLen int) ([]byte, error) { if dataLen != fixLen { - return nil, fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen), + } } return []byte{}, nil diff --git a/prefix/ebcdic1047.go b/prefix/ebcdic1047.go index d1d138c3..b46627ad 100644 --- a/prefix/ebcdic1047.go +++ b/prefix/ebcdic1047.go @@ -24,11 +24,15 @@ type ebcdic1047Prefixer struct { func (p *ebcdic1047Prefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { if dataLen > maxLen { - return nil, fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen), + } } if len(strconv.Itoa(dataLen)) > p.digits { - return nil, fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.digits) + return nil, &LengthError{ + fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.digits), + } } strLen := fmt.Sprintf("%0*d", p.digits, dataLen) @@ -41,7 +45,9 @@ func (p *ebcdic1047Prefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { func (p *ebcdic1047Prefixer) DecodeLength(maxLen int, data []byte) (int, int, error) { if len(data) < p.digits { - return 0, 0, fmt.Errorf(notEnoughDataToRead, len(data), p.digits) + return 0, 0, &LengthError{ + fmt.Errorf(notEnoughDataToRead, len(data), p.digits), + } } decodedData, _, err := encoding.EBCDIC1047.Decode(data[:p.digits], p.digits) @@ -55,7 +61,9 @@ func (p *ebcdic1047Prefixer) DecodeLength(maxLen int, data []byte) (int, int, er } if dataLen > maxLen { - return 0, 0, fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen) + return 0, 0, &LengthError{ + fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen), + } } return dataLen, p.digits, nil @@ -69,7 +77,9 @@ type ebcdic1047FixedPrefixer struct{} func (p *ebcdic1047FixedPrefixer) EncodeLength(fixLen, dataLen int) ([]byte, error) { if dataLen != fixLen { - return nil, fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen), + } } return []byte{}, nil diff --git a/prefix/ebcdic1047_test.go b/prefix/ebcdic1047_test.go index 6b6cca5f..5845a945 100644 --- a/prefix/ebcdic1047_test.go +++ b/prefix/ebcdic1047_test.go @@ -123,25 +123,25 @@ func TestEBCDIC1047PrefixersEncodeErrors(t *testing.T) { prefixer: EBCDIC1047.L, maxLen: 8, dataLen: 9, - expectedError: "field length: 9 is larger than maximum: 8", + expectedError: "data length: 9 is larger than maximum: 8", }, { prefixer: EBCDIC1047.LL, maxLen: 52, dataLen: 73, - expectedError: "field length: 73 is larger than maximum: 52", + expectedError: "data length: 73 is larger than maximum: 52", }, { prefixer: EBCDIC1047.LLL, maxLen: 512, dataLen: 999, - expectedError: "field length: 999 is larger than maximum: 512", + expectedError: "data length: 999 is larger than maximum: 512", }, { prefixer: EBCDIC1047.LLLL, maxLen: 1024, dataLen: 2048, - expectedError: "field length: 2048 is larger than maximum: 1024", + expectedError: "data length: 2048 is larger than maximum: 1024", }, } { encoded, err := testCase.prefixer.EncodeLength(testCase.maxLen, testCase.dataLen) @@ -189,6 +189,7 @@ func TestEBCDIC1047PrefixersEncodeErrors(t *testing.T) { encoded, err := testCase.prefixer.EncodeLength(testCase.maxLen, testCase.dataLen) require.Nil(t, encoded) require.EqualError(t, err, testCase.expectedError) + require.True(t, IsLengthError(err), "error should be a length error") } }) @@ -196,7 +197,8 @@ func TestEBCDIC1047PrefixersEncodeErrors(t *testing.T) { t.Parallel() encoded, err := EBCDIC1047.Fixed.EncodeLength(128, 127) require.Nil(t, encoded) - require.EqualError(t, err, "field length: 127 should be fixed: 128") + require.EqualError(t, err, "data length: 127 should be fixed: 128") + require.True(t, IsLengthError(err), "error should be a length error") }) } @@ -334,6 +336,7 @@ func TestEBCDIC1047PrefixersDecodeErrors(t *testing.T) { require.Zero(t, length) require.Zero(t, read) require.EqualError(t, err, testCase.expectedError) + require.True(t, IsLengthError(err), "error should be a length error") } }) diff --git a/prefix/ebcdic_test.go b/prefix/ebcdic_test.go index e5fb39ae..11a5e5e6 100644 --- a/prefix/ebcdic_test.go +++ b/prefix/ebcdic_test.go @@ -10,18 +10,21 @@ func TestEBCDICVarPrefixer_EncodeLengthDigitsValidation(t *testing.T) { _, err := EBCDIC.LL.EncodeLength(999, 123) require.Contains(t, err.Error(), "number of digits in length: 123 exceeds: 2") + require.True(t, IsLengthError(err), "error should be a length error") } func TestEBCDICVarPrefixer_EncodeLengthMaxLengthValidation(t *testing.T) { _, err := EBCDIC.LL.EncodeLength(20, 22) - require.Contains(t, err.Error(), "field length: 22 is larger than maximum: 20") + require.Contains(t, err.Error(), "data length: 22 is larger than maximum: 20") + require.True(t, IsLengthError(err), "error should be a length error") } func TestEBCDICVarPrefixer_DecodeLengthMaxLengthValidation(t *testing.T) { _, _, err := EBCDIC.LLL.DecodeLength(20, []byte{0x22}) require.Contains(t, err.Error(), "not enough data length: 3 to read: 1 byte digits") + require.True(t, IsLengthError(err), "error should be a length error") } func TestEBCDICVarPrefixer_LHelpers(t *testing.T) { @@ -85,10 +88,12 @@ func TestEBCDICFixedPrefixer_EncodeLengthValidation(t *testing.T) { _, err := pref.EncodeLength(8, 12) require.Error(t, err) - require.Contains(t, err.Error(), "field length: 12 should be fixed: 8") + require.Contains(t, err.Error(), "data length: 12 should be fixed: 8") + require.True(t, IsLengthError(err), "error should be a length error") _, err = pref.EncodeLength(8, 6) require.Error(t, err) - require.Contains(t, err.Error(), "field length: 6 should be fixed: 8") + require.Contains(t, err.Error(), "data length: 6 should be fixed: 8") + require.True(t, IsLengthError(err), "error should be a length error") } diff --git a/prefix/error.go b/prefix/error.go index 8abb9c12..f3033956 100644 --- a/prefix/error.go +++ b/prefix/error.go @@ -1,8 +1,29 @@ package prefix -const fieldLengthIsLargerThanMax = "field length: %d is larger than maximum: %d" +import "errors" + +const fieldLengthIsLargerThanMax = "data length: %d is larger than maximum: %d" const numberOfDigitsInLengthExceeds = "number of digits in length: %d exceeds: %d" const notEnoughDataToRead = "not enough data length: %d to read: %d byte digits" const invalidLength = "invalid length: %d" const dataLengthIsLargerThanMax = "data length: %d is larger than maximum %d" -const fieldLengthShouldBeFixed = "field length: %d should be fixed: %d" +const fieldLengthShouldBeFixed = "data length: %d should be fixed: %d" + +type LengthError struct { + err error +} + +func (e *LengthError) Error() string { + if e.err == nil { + return "" + } + return e.err.Error() +} + +func IsLengthError(err error) bool { + e := &LengthError{} + if errors.As(err, &e) { + return true + } + return false +} diff --git a/prefix/hex.go b/prefix/hex.go index bacc7af5..68db6171 100644 --- a/prefix/hex.go +++ b/prefix/hex.go @@ -24,7 +24,9 @@ type hexFixedPrefixer struct { func (p *hexFixedPrefixer) EncodeLength(fixLen, dataLen int) ([]byte, error) { // for ascii hex the length is x2 (ascii hex digit takes one byte) if dataLen != fixLen*2 { - return nil, fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen*2) + return nil, &LengthError{ + fmt.Errorf(fieldLengthShouldBeFixed, dataLen, fixLen*2), + } } return []byte{}, nil @@ -44,12 +46,16 @@ type hexVarPrefixer struct { func (p *hexVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { if dataLen > maxLen { - return nil, fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen) + return nil, &LengthError{ + fmt.Errorf(fieldLengthIsLargerThanMax, dataLen, maxLen), + } } maxPossibleLength := 1<<(p.Digits*8) - 1 if dataLen > maxPossibleLength { - return nil, fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits) + return nil, &LengthError{ + fmt.Errorf(numberOfDigitsInLengthExceeds, dataLen, p.Digits), + } } strLen := strconv.FormatInt(int64(dataLen), 16) @@ -61,7 +67,9 @@ func (p *hexVarPrefixer) EncodeLength(maxLen, dataLen int) ([]byte, error) { func (p *hexVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, error) { length := hex.EncodedLen(p.Digits) if len(data) < length { - return 0, 0, fmt.Errorf(notEnoughDataToRead, length, len(data)) + return 0, 0, &LengthError{ + fmt.Errorf(notEnoughDataToRead, length, len(data)), + } } dataLen, err := strconv.ParseUint(string(data[:length]), 16, p.Digits*8) @@ -70,12 +78,16 @@ func (p *hexVarPrefixer) DecodeLength(maxLen int, data []byte) (int, int, error) } if dataLen > math.MaxInt { - return 0, 0, fmt.Errorf("data length %d exceeds maximum int value", dataLen) + return 0, 0, &LengthError{ + fmt.Errorf("data length %d exceeds maximum int value", dataLen), + } } // #nosec G115 -- dataLen is validated to be within MaxInt range above if int(dataLen) > maxLen { - return 0, 0, fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen) + return 0, 0, &LengthError{ + fmt.Errorf(dataLengthIsLargerThanMax, dataLen, maxLen), + } } // #nosec G115 -- dataLen is validated to be within MaxInt range above