diff --git a/examples/gno.land/p/demo/bitmap/bitmap.gno b/examples/gno.land/p/demo/bitmap/bitmap.gno new file mode 100644 index 00000000000..a351d8c5e54 --- /dev/null +++ b/examples/gno.land/p/demo/bitmap/bitmap.gno @@ -0,0 +1,58 @@ +package bitmap + +import ( + "gno.land/p/demo/ufmt" +) + +// A simple implementation of Bitmap + +// Bitmap represents a bitmap using a slice of bytes +type Bitmap struct { + data []byte +} + +// NewBitmap creates a new Bitmap with a specific size (in bits) +func New(size uint64) *Bitmap { + byteSize := (size + 7) / 8 // Calculate the number of bytes needed + return &Bitmap{ + data: make([]byte, byteSize), + } +} + +// MustSet sets the bit at the given index (0-based) and returns an error if out of bounds +func (b *Bitmap) Set(index uint64) error { + if index >= uint64(len(b.data))*8 { + return ufmt.Errorf("Index out of bounds") + } + + byteIndex := index / 8 + bitIndex := index % 8 + + b.data[byteIndex] |= 1 << uint(bitIndex) // Set the corresponding bit using bitwise OR + + return nil +} + +// Set sets the bit at the given index (0-based) +func (b *Bitmap) MustSet(index uint64) { + if index >= uint64(len(b.data))*8 { + panic("Index out of bounds") + } + + byteIndex := index / 8 + bitIndex := index % 8 + + b.data[byteIndex] |= 1 << uint(bitIndex) // Set the corresponding bit using bitwise OR +} + +// Get checks if the bit at the given index is set +func (b *Bitmap) Get(index uint64) bool { + if index >= uint64(len(b.data))*8 { + panic("Index out of bounds") + } + + byteIndex := index / 8 + bitIndex := index % 8 + + return b.data[byteIndex]&(1< 0 // Check if the corresponding bit is set using bitwise AND +} diff --git a/examples/gno.land/p/demo/bitmap/bitmap_test.gno b/examples/gno.land/p/demo/bitmap/bitmap_test.gno new file mode 100644 index 00000000000..78641f6e02c --- /dev/null +++ b/examples/gno.land/p/demo/bitmap/bitmap_test.gno @@ -0,0 +1,96 @@ +package bitmap + +import ( + "testing" +) + +func TestBitmap_New(t *testing.T) { + size := uint64(16) + bm := New(size) + + if len(bm.data)*8 != int(size) { + t.Errorf("Expected bitmap size: %d, got: %d", size, len(bm.data)*8) + } +} + +func TestBitmap_SetAndGet(t *testing.T) { + bm := New(16) + + // Test setting and getting bits within bounds + err := bm.Set(2) + if err != nil { + t.Errorf("Expected no error, got: %v", err) + } + + if !bm.Get(2) { + t.Errorf("Expected bit at index 2 to be set") + } + + err = bm.Set(15) + if err != nil { + t.Errorf("Expected no error, got: %v", err) + } + + if !bm.Get(15) { + t.Errorf("Expected bit at index 15 to be set") + } + + // Test setting and getting bits out of bounds + err = bm.Set(16) + if err == nil { + t.Errorf("Expected error, got: nil") + } +} + +func TestBitmap_MustSet(t *testing.T) { + bm := New(16) + + // Test setting bits within bounds + defer func() { + if r := recover(); r != nil { + t.Errorf("Expected no panic, but got panic: %v", r) + } + }() + + bm.MustSet(2) + if !bm.Get(2) { + t.Errorf("Expected bit at index 2 to be set") + } + + bm.MustSet(15) + if !bm.Get(15) { + t.Errorf("Expected bit at index 15 to be set") + } + + // Test setting bits out of bounds + defer func() { + if r := recover(); r == nil { + t.Errorf("Expected panic, but no panic occurred") + } + }() + + bm.MustSet(16 * 8) +} + +func TestBitmap_Get(t *testing.T) { + bm := New(16) + + // Test getting bits within bounds + bm.MustSet(2) + if !bm.Get(2) { + t.Errorf("Expected bit at index 2 to be set") + } + + if bm.Get(3) { + t.Errorf("Expected bit at index 3 to be unset") + } + + // Test getting bits out of bounds + defer func() { + if r := recover(); r == nil { + t.Errorf("Expected panic, but no panic occurred") + } + }() + + bm.Get(16 * 8) +} diff --git a/examples/gno.land/p/demo/bitmap/gno.mod b/examples/gno.land/p/demo/bitmap/gno.mod new file mode 100644 index 00000000000..57cb384bee6 --- /dev/null +++ b/examples/gno.land/p/demo/bitmap/gno.mod @@ -0,0 +1,3 @@ +module gno.land/p/demo/bitmap + +require gno.land/p/demo/ufmt v0.0.0-latest