Skip to content

fix: use minimal integer encoding and decode fixint bytes#13

Merged
medvednikov merged 2 commits into
masterfrom
fix-minimal-int-encoding
May 26, 2026
Merged

fix: use minimal integer encoding and decode fixint bytes#13
medvednikov merged 2 commits into
masterfrom
fix-minimal-int-encoding

Conversation

@medvednikov
Copy link
Copy Markdown
Member

Summary

Fixes three interop-breaking bugs in the integer encode/decode paths, reported in vlang/v#26644.

  • Encoder always used the widest int format. encode(0) produced d2 00 00 00 00 instead of 00. The generic encode[T]() dispatcher bypassed the existing encode_int/encode_uint functions (which already implement minimal encoding) and called fixed-width helpers directly. Now all integer types route through encode_int/encode_uint. The missing i32 case is also added.
  • positive_int_unsigned defaulted to false. Non-negative values 128–255 took the signed branch and encoded as 3-byte int16 instead of 2-byte uint8. Default config now sets it to true.
  • Decoder ignored positive/negative fixint bytes. decode_integer and decode_to_json had no match arms for 0x000x7f or 0xe00xff, so any value in -32..127 encoded by a spec-compliant library (Python, Rust, Go) — or by this library after the encoder fix — could not be decoded. Both functions now handle the fixint ranges.

encode_test.v assertions are updated to the spec-compliant minimal bytes.

Test plan

  • v test . — all 3 test files pass (decode, encode, decode_to_json)
  • Verified spec bytes against the MessagePack int format family:
    • encode(0)00, encode(42)2a, encode(127)7f
    • encode(-32)e0, encode(-123)d0 85, encode(-1)ff
    • encode(200)cc c8 (uint8, not signed int16)
    • encode([1,2,3])93 01 02 03
  • Round-trip: decode(encode(x)) for fixint and uint8 ranges
  • Decode of standalone fixint bytes (2a, 00, fb, e0, ff)

Encoder now routes all integer types through encode_int/encode_uint so
the smallest format that fits is always selected (positive/negative
fixint, u8/u16/u32/u64, i8/i16/i32/i64), per the MessagePack spec's
minimal-encoding requirement. Default config flips
positive_int_unsigned to true so non-negative values use the more
compact unsigned family. Decoder gains match arms for positive fixint
(0x00-0x7f) and negative fixint (0xe0-0xff) in both decode_integer and
decode_to_json, fixing inability to decode output from spec-compliant
implementations (Python, Rust, Go) and from this library's own
corrected encoder. Test assertions updated to spec-compliant bytes.

Reported in vlang/v#26644.
@medvednikov medvednikov merged commit d5fec07 into master May 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant