diff --git a/lib/debezium/converters/bit.go b/lib/debezium/converters/bit.go index 18707920..e09c36cc 100644 --- a/lib/debezium/converters/bit.go +++ b/lib/debezium/converters/bit.go @@ -1,7 +1,10 @@ package converters import ( + "bytes" + "encoding/binary" "fmt" + "math" "strconv" "github.com/artie-labs/transfer/lib/debezium" @@ -65,6 +68,23 @@ func (b BitConverter) Convert(value any) (any, error) { return nil, fmt.Errorf("failed to convert binary string %q to integer: %w", stringValue, err) } - return []byte{byte(intValue)}, nil + return intToByteA( + intValue, + // Calculate the number of bytes by dividing the number of bits by 8 and rounding up + int(math.Ceil(float64(b.charMaxLength)/8.0)), + ) } } + +// intToByteA - Converts an integer to a byte array of the specified length, using little endian, which mirrors the same logic as java.util.BitSet +// Ref: https://docs.oracle.com/javase/7/docs/api/java/util/BitSet.html +func intToByteA(intValue int64, byteLength int) ([]byte, error) { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.LittleEndian, intValue); err != nil { + return nil, fmt.Errorf("failed to write bytes: %w", err) + } + + // Truncate the buffer to the required length (because binary.Write will write 8 bytes for an int64) + result := buf.Bytes() + return result[:byteLength], nil +} diff --git a/lib/debezium/converters/bit_test.go b/lib/debezium/converters/bit_test.go index 74e37715..62b9cca5 100644 --- a/lib/debezium/converters/bit_test.go +++ b/lib/debezium/converters/bit_test.go @@ -63,7 +63,7 @@ func TestBitConverter_Convert(t *testing.T) { } } { - // char max size + // char max size - 5 { // Invalid, length not matching converter := NewBitConverter(5) @@ -91,4 +91,25 @@ func TestBitConverter_Convert(t *testing.T) { assert.Equal(t, []byte{19}, value) } } + { + // char max size - 10 + converter := NewBitConverter(10) + value, err := converter.Convert("1000000011") + assert.NoError(t, err) + assert.Equal(t, []byte{3, 2}, value) + } + { + // char max size - 17 + converter := NewBitConverter(17) + value, err := converter.Convert("10000000111111111") + assert.NoError(t, err) + assert.Equal(t, []byte{255, 1, 1}, value) + } + { + // char max size - 24 + converter := NewBitConverter(24) + value, err := converter.Convert("110110101111000111100101") + assert.NoError(t, err) + assert.Equal(t, []byte{229, 241, 218}, value) + } }