Skip to content

Conversation

@karkowg
Copy link
Contributor

@karkowg karkowg commented Jan 12, 2026

Greptile Overview

Greptile Summary

This PR represents a major v1.0.0 refactor that consolidates the bitmask API into a single, immutable class with improved enum support.

Key Changes:

  • Consolidated BaseBitmask, TinyBitmask, SmallBitmask, and MediumBitmask into a single immutable Bitmask class
  • Added factory methods (make(), tiny(), small(), medium()) for different bit sizes
  • Implemented direct BackedEnum and UnitEnum support in all methods via the new maskValue() helper
  • Replaced MaxValue enum with Size enum that computes maxValue() dynamically
  • Made the class final and readonly for immutability guarantees
  • All operations (set, unset, toggle) now return new instances instead of mutating state
  • Removed deprecated PowerOfTwo value object in favor of isPowerOfTwo() helper function
  • Updated all playground examples to use the new API
  • Added comprehensive CI workflow testing PHP 8.2-8.4 with linting, static analysis, and unit tests

Architecture Improvements:

  • The new design eliminates class hierarchy complexity while maintaining type safety
  • Enum support allows cleaner API usage without manual ->value extraction
  • Immutability prevents accidental state mutations and makes the class thread-safe
  • Size validation is now centralized and computed rather than hardcoded

Confidence Score: 4/5

  • This PR is safe to merge with minor considerations for the unset operation
  • The refactor is well-tested with comprehensive test coverage including boundary tests, enum support tests, and immutability tests. The code is clean and follows PHP 8.2+ best practices. Score is 4/5 rather than 5/5 due to one minor consideration: the unset() method doesn't validate the result after bitwise NOT operation, though tests suggest this works correctly in practice.
  • Pay attention to src/Bitmask.php unset method (line 66-71) - while tests pass, the bitwise NOT operation could theoretically produce unexpected results with PHP's signed integer handling

Important Files Changed

File Analysis

Filename Score Overview
src/Bitmask.php 4/5 Refactored from inheritance to a single immutable class with enum support and size variants
src/Support/helpers.php 5/5 Added maskValue() helper to convert UnitEnum and BackedEnum to integer values
src/Enums/Size.php 5/5 Replaced MaxValue enum with Size enum that computes maxValue dynamically
tests/BitmaskSpec.php 5/5 Comprehensive tests covering all operations, enum support, size boundaries, and immutability
.github/workflows/ci.yml 5/5 New CI workflow with PHP 8.2-8.4 matrix testing, linting, static analysis, and tests

Sequence Diagram

sequenceDiagram
    participant User
    participant Bitmask
    participant maskValue
    participant isPowerOfTwo
    participant Size

    User->>Bitmask: make(Flag::A, Size::UInt8)
    Bitmask->>maskValue: maskValue(Flag::A)
    alt BackedEnum
        maskValue-->>Bitmask: flag.value
    else UnitEnum
        maskValue-->>Bitmask: 1 << position
    else int
        maskValue-->>Bitmask: flag
    end
    Bitmask->>Size: size.maxValue()
    Size-->>Bitmask: (1 << bits) - 1
    Bitmask->>Bitmask: Validate value <= maxValue
    Bitmask-->>User: Bitmask instance

    User->>Bitmask: set(Flag::B)
    Bitmask->>maskValue: maskValue(Flag::B)
    maskValue-->>Bitmask: flagValue
    Bitmask->>isPowerOfTwo: isPowerOfTwo(flagValue)
    isPowerOfTwo-->>Bitmask: true
    Bitmask->>Bitmask: newValue = value | flagValue
    Bitmask->>Bitmask: Validate newValue <= maxValue
    Bitmask->>Bitmask: new Bitmask(newValue, size)
    Bitmask-->>User: New immutable instance

    User->>Bitmask: has(Flag::B)
    Bitmask->>maskValue: maskValue(Flag::B)
    maskValue-->>Bitmask: flagValue
    Bitmask->>isPowerOfTwo: isPowerOfTwo(flagValue)
    isPowerOfTwo-->>Bitmask: true
    Bitmask->>Bitmask: (value & flagValue) === flagValue
    Bitmask-->>User: boolean result

    User->>Bitmask: unset(Flag::B)
    Bitmask->>maskValue: maskValue(Flag::B)
    maskValue-->>Bitmask: flagValue
    Bitmask->>isPowerOfTwo: isPowerOfTwo(flagValue)
    isPowerOfTwo-->>Bitmask: true
    Bitmask->>Bitmask: value & (~flagValue)
    Bitmask->>Bitmask: new Bitmask(result, size)
    Bitmask-->>User: New immutable instance
Loading

@karkowg
Copy link
Contributor Author

karkowg commented Jan 12, 2026

@greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No files reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, no comments

Edit Code Review Agent Settings | Greptile

@karkowg karkowg merged commit 2a8945a into main Jan 12, 2026
28 of 31 checks passed
@karkowg karkowg deleted the 1.x branch January 12, 2026 03:34
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.

2 participants