Skip to content

Fix RK decoding and MULRK column offset#1

Open
ketbra wants to merge 1 commit into
PleaseDont:mainfrom
ketbra:mulrk_fixes
Open

Fix RK decoding and MULRK column offset#1
ketbra wants to merge 1 commit into
PleaseDont:mainfrom
ketbra:mulrk_fixes

Conversation

@ketbra

@ketbra ketbra commented Jan 16, 2026

Copy link
Copy Markdown

Bug 1: Incorrect RK value decoding (xlrd-local/src/record/rk.rs)

Root cause: The RK record format stores numbers in a compressed 4-byte format where:

  • Bit 0 (fX100): If set, divide result by 100
  • Bit 1 (fInt): If 0, value is IEEE 754 float; if 1, value is integer
  • Bits 2-31: The encoded value

The original code had:

  1. #[skip] on fint which excluded it from the bitfield entirely (corrupting the bit layout)
  2. Always treated values as integers, never decoding floats

Fix: Changed #[skip] to #[skip(setters)] and added proper decode_rk_value() function that checks fint and decodes floats by reconstructing the IEEE 754 double.

Bug 2: Off-by-one column offset (xlrd-local/src/lib.rs:367)

Root cause: MULRK record processing started with let mut col = 1; but should be let mut col = 0; since BIFF column indices are 0-based.

Result: All values from MULRK records were placed one column to the right of their correct position.

Fix: Changed let mut col = 1; to let mut col = 0;.

Bug 1: Incorrect RK value decoding (xlrd-local/src/record/rk.rs)

 Root cause: The RK record format stores numbers in a compressed 4-byte format where:
 - Bit 0 (fX100): If set, divide result by 100
 - Bit 1 (fInt): If 0, value is IEEE 754 float; if 1, value is integer
 - Bits 2-31: The encoded value

 The original code had:
 1. #[skip] on fint which excluded it from the bitfield entirely (corrupting the bit layout)
 2. Always treated values as integers, never decoding floats

 Fix: Changed #[skip] to #[skip(setters)] and added proper decode_rk_value() function that checks fint and decodes floats by reconstructing the IEEE 754 double.

Bug 2: Off-by-one column offset (xlrd-local/src/lib.rs:367)

 Root cause: MULRK record processing started with let mut col = 1; but should be let mut col = 0; since BIFF column indices are 0-based.

 Result: All values from MULRK records were placed one column to the right of their correct position.

 Fix: Changed let mut col = 1; to let mut col = 0;.
ketbra pushed a commit to ketbra/xlrd that referenced this pull request Jan 16, 2026
Port fixes from upstream PR PleaseDont#1

Bug 1: RK Value Decoding
- The fint field was marked with #[skip] which completely ignored it
- Code treated all values as integers, but when fint=false the 30 bits
  are the HIGH bits of an IEEE 754 64-bit floating-point number
- Fix: Add decode_rk_value() function that properly handles both cases:
  - fint=true: Sign-extend and interpret as 30-bit signed integer
  - fint=false: Reconstruct IEEE 754 double from high 30 bits
- Apply fx100 division after decoding

Bug 2: MULRK Column Offset
- Column tracking started at 1 instead of 0
- BIFF uses 0-based column indexing, so this shifted all values
  one column to the right
- Fix: Change `let mut col = 1;` to `let mut col = 0;`

Changes:
- src/record/rk.rs: Add decode_rk_value() function, fix fint handling
- src/record/mulrk.rs: Use decode_rk_value() for consistent decoding
- src/lib.rs: Fix MULRK column offset (col = 0)
- tests/test_rk_decoding.rs: Add tests for RK and MULRK decoding

All 77 tests pass.
mattf-intex pushed a commit to mattf-intex/xlrd that referenced this pull request Feb 12, 2026
Fix RK decoding and MULRK column offset
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