Skip to content

Commit

Permalink
fix: Maintain backward-compatibility with old bitstring implementation (
Browse files Browse the repository at this point in the history
#1804)

For VC DM1.1 status lists, maintain backward compatibility with the old bitstring implementation where bits are set in the "right-to-left" order.

Signed-off-by: Bob Stasyszyn <bob.stasyszyn@gendigital.com>
  • Loading branch information
bstasyszyn authored Nov 25, 2024
1 parent 7f0fac9 commit a71c34f
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 12 deletions.
40 changes: 28 additions & 12 deletions pkg/doc/vc/bitstring/bitstring.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ const (
// BitString struct.
type BitString struct {
bits []byte
numBits int
multibaseEncoding multibase.Encoding
bitPosition func(position int) int
}

type Opt func(*options)
Expand All @@ -43,19 +43,38 @@ func WithMultibaseEncoding(value multibase.Encoding) Opt {

// NewBitString return bitstring.
func NewBitString(length int, opts ...Opt) *BitString {
size := 1 + ((length - 1) / bitsPerByte)

return newBitString(make([]byte, size), opts)
}

func newBitString(bits []byte, opts []Opt) *BitString {
options := &options{}

for _, opt := range opts {
opt(options)
}

size := 1 + ((length - 1) / bitsPerByte)

return &BitString{
bits: make([]byte, size),
numBits: length,
b := &BitString{
bits: bits,
multibaseEncoding: options.multibaseEncoding,
}

if options.multibaseEncoding != multibase.Encoding(0) {
// VC DM2.0 BitstringStatusList uses multibase encoding and requires bits
// to be set left-to-right.
b.bitPosition = func(position int) int {
return bitOffset - (position % bitsPerByte)
}
} else {
// Maintain backward compatibility with the previous implementation,
// which sets bits right-to-left.
b.bitPosition = func(position int) int {
return position % bitsPerByte
}
}

return b
}

// DecodeBits decode bits.
Expand Down Expand Up @@ -101,16 +120,13 @@ func DecodeBits(encodedBits string, opts ...Opt) (*BitString, error) {
return nil, err
}

return &BitString{
bits: buf.Bytes(),
multibaseEncoding: options.multibaseEncoding,
}, nil
return newBitString(buf.Bytes(), opts), nil
}

// Set bit.
func (b *BitString) Set(position int, bitSet bool) error {
nByte := position / bitsPerByte
nBit := bitOffset - (position % bitsPerByte)
nBit := b.bitPosition(position)

if position < 0 || nByte > len(b.bits)-1 {
return fmt.Errorf("position is invalid")
Expand All @@ -130,7 +146,7 @@ func (b *BitString) Set(position int, bitSet bool) error {
// Get bit.
func (b *BitString) Get(position int) (bool, error) {
nByte := position / bitsPerByte
nBit := bitOffset - (position % bitsPerByte)
nBit := b.bitPosition(position)

if position < 0 || nByte > len(b.bits)-1 {
return false, fmt.Errorf("position is invalid")
Expand Down
39 changes: 39 additions & 0 deletions pkg/doc/vc/bitstring/bitstring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
package bitstring

import (
"fmt"
"testing"

"github.com/multiformats/go-multibase"
Expand Down Expand Up @@ -53,6 +54,14 @@ func TestBitString(t *testing.T) {
err := bitString.Set(1, true)
require.NoError(t, err)

err = bitString.Set(14, true)
require.NoError(t, err)

err = bitString.Set(17, true)
require.NoError(t, err)

logBits(t, bitString)

bitSet, err := bitString.Get(1)
require.NoError(t, err)
require.True(t, bitSet)
Expand Down Expand Up @@ -89,6 +98,14 @@ func TestBitString(t *testing.T) {
err := bitString.Set(1, true)
require.NoError(t, err)

err = bitString.Set(14, true)
require.NoError(t, err)

err = bitString.Set(17, true)
require.NoError(t, err)

logBits(t, bitString)

bitSet, err := bitString.Get(1)
require.NoError(t, err)
require.True(t, bitSet)
Expand Down Expand Up @@ -117,5 +134,27 @@ func TestBitString(t *testing.T) {
bitSet, err = bitStr.Get(1)
require.NoError(t, err)
require.False(t, bitSet)

bitSet, err = bitStr.Get(14)
require.NoError(t, err)
require.True(t, bitSet)

bitSet, err = bitStr.Get(17)
require.NoError(t, err)
require.True(t, bitSet)

logBits(t, bitStr)
})
}

func logBits(t *testing.T, b *BitString) {
t.Helper()

var str string

for _, x := range b.bits {
str += fmt.Sprintf("%08b ", x)
}

t.Logf("BitString: %s", str)
}

0 comments on commit a71c34f

Please sign in to comment.