SwiftCBOR
SwiftCBOR copied to clipboard
Incorrect encoding of negative 64 bit int
Hello! Thanks for a great library!
I noticed that the encoding of negative 64 bit integers are wrong. You need to subtract 1 to get the correct value. See the RFC 7049
Major type 1: a negative integer. The encoding follows the rules
for unsigned integers (major type 0), except that the value is
then -1 minus the encoded unsigned integer. For example, the
integer -500 would be 0b001_11001 (major type 1, additional
information 25) followed by the two bytes 0x01f3, which is 499 in
decimal.
But you are doing the two's complement:
public static func encodeNegativeInt(_ x: Int64) -> [UInt8] {
assert(x < 0)
var res = encodeVarUInt(~UInt64(bitPattern: x))
res[0] = res[0] | 0b001_00000
return res
}
I got it working by subtracting 1. I also added a static func accepting Int64
, like this:
public extension CBOR {
static func int64(_ int: Int64) -> CBOR {
if int < 0 {
return CBOR.negativeInt(UInt64(abs(int)-1))
} else {
return CBOR.unsignedInt(UInt64(int))
}
}
}
You could probably add a few test cases in your unit test where you explicitly test UInt64 :)
Thx!
NegativeInt
not storing the actual usable number is intentional — to make encoded negative max int representable — and mentioned in the readme:
Negative integers are decoded as NegativeInt(UInt), where the actual number is -1 - i (CBOR's negative integers can be larger than 64-bit signed integers).
I guess convenience functions like your int64
would be good, I'd accept a PR with that.