Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use "cbor:" prefixed error msg when decoding with non-default TimeTagToAnyMode setting #544

Merged
merged 2 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -1874,23 +1874,25 @@ func (d *decoder) parse(skipSelfDescribedTag bool) (interface{}, error) { //noli
if tagNum == 1 {
tm = tm.UTC()
}
// Formats to RFC3339 and errors on time.Time values that cannot be
// represented by RFC3339.
// Call time.MarshalText() to format decoded time to RFC3339 format,
// and return error on time value that cannot be represented in
// RFC3339 format. E.g. year cannot exceed 9999, etc.
text, err := tm.Truncate(time.Second).MarshalText()
if err != nil {
return nil, err
return nil, fmt.Errorf("cbor: decoded time cannot be represented in RFC3339 format: %v", err)
}
return string(text), nil

case TimeTagToRFC3339Nano:
if tagNum == 1 {
tm = tm.UTC()
}
// Formats to RFC3339 with subsecond precision and errors on
// time.Time values that cannot be represented by RFC3339.
// Call time.MarshalText() to format decoded time to RFC3339 format,
// and return error on time value that cannot be represented in
// RFC3339 format with sub-second precision.
text, err := tm.MarshalText()
if err != nil {
return nil, err
return nil, fmt.Errorf("cbor: decoded time cannot be represented in RFC3339 format with sub-second precision: %v", err)
}
return string(text), nil

Expand Down
4 changes: 2 additions & 2 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8915,13 +8915,13 @@ func TestDecModeTimeTagToAny(t *testing.T) {
name: "error under TimeTagToRFC3339 when tag 1 represents a time that can't be represented by valid RFC3339",
opts: DecOptions{TimeTagToAny: TimeTagToRFC3339},
in: hexDecode("c11b0000003afff44181"), // 1(253402300801)
wantErrMessage: "Time.MarshalText: year outside of range [0,9999]",
wantErrMessage: "cbor: decoded time cannot be represented in RFC3339 format: Time.MarshalText: year outside of range [0,9999]",
},
{
name: "error under TimeTagToRFC3339Nano when tag 1 represents a time that can't be represented by valid RFC3339",
opts: DecOptions{TimeTagToAny: TimeTagToRFC3339Nano},
in: hexDecode("c11b0000003afff44181"), // 1(253402300801)
wantErrMessage: "Time.MarshalText: year outside of range [0,9999]",
wantErrMessage: "cbor: decoded time cannot be represented in RFC3339 format with sub-second precision: Time.MarshalText: year outside of range [0,9999]",
},
} {
t.Run(tc.name, func(t *testing.T) {
Expand Down
34 changes: 23 additions & 11 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,9 @@ func encodeFloat(e *bytes.Buffer, em *encMode, v reflect.Value) error {
if v.Kind() == reflect.Float64 && (fopt == ShortestFloatNone || cannotFitFloat32(f64)) {
// Encode float64
// Don't use encodeFloat64() because it cannot be inlined.
var scratch [9]byte
const argumentSize = 8
const headSize = 1 + argumentSize
var scratch [headSize]byte
scratch[0] = byte(cborTypePrimitives) | byte(additionalInformationAsFloat64)
binary.BigEndian.PutUint64(scratch[1:], math.Float64bits(f64))
e.Write(scratch[:])
Expand All @@ -1005,20 +1007,24 @@ func encodeFloat(e *bytes.Buffer, em *encMode, v reflect.Value) error {
if p == float16.PrecisionExact {
// Encode float16
// Don't use encodeFloat16() because it cannot be inlined.
var scratch [3]byte
const argumentSize = 2
const headSize = 1 + argumentSize
var scratch [headSize]byte
scratch[0] = byte(cborTypePrimitives) | additionalInformationAsFloat16
binary.BigEndian.PutUint16(scratch[1:], uint16(f16))
e.Write(scratch[:3])
e.Write(scratch[:])
return nil
}
}

// Encode float32
// Don't use encodeFloat32() because it cannot be inlined.
var scratch [5]byte
const argumentSize = 4
const headSize = 1 + argumentSize
var scratch [headSize]byte
scratch[0] = byte(cborTypePrimitives) | additionalInformationAsFloat32
binary.BigEndian.PutUint32(scratch[1:], math.Float32bits(f32))
e.Write(scratch[:5])
e.Write(scratch[:])
return nil
}

Expand Down Expand Up @@ -1104,26 +1110,32 @@ func encodeNaN(e *bytes.Buffer, em *encMode, v reflect.Value) error {
}

func encodeFloat16(e *bytes.Buffer, f16 float16.Float16) error {
var scratch [3]byte
const argumentSize = 2
const headSize = 1 + argumentSize
var scratch [headSize]byte
scratch[0] = byte(cborTypePrimitives) | additionalInformationAsFloat16
binary.BigEndian.PutUint16(scratch[1:], uint16(f16))
e.Write(scratch[:3])
e.Write(scratch[:])
return nil
}

func encodeFloat32(e *bytes.Buffer, f32 float32) error {
var scratch [5]byte
const argumentSize = 4
const headSize = 1 + argumentSize
var scratch [headSize]byte
scratch[0] = byte(cborTypePrimitives) | additionalInformationAsFloat32
binary.BigEndian.PutUint32(scratch[1:], math.Float32bits(f32))
e.Write(scratch[:5])
e.Write(scratch[:])
return nil
}

func encodeFloat64(e *bytes.Buffer, f64 float64) error {
var scratch [9]byte
const argumentSize = 8
const headSize = 1 + argumentSize
var scratch [headSize]byte
scratch[0] = byte(cborTypePrimitives) | additionalInformationAsFloat64
binary.BigEndian.PutUint64(scratch[1:], math.Float64bits(f64))
e.Write(scratch[:9])
e.Write(scratch[:])
return nil
}

Expand Down
Loading