Rubyでビットの修正を行う方法


Rubyで指定したビットの修正を行う方法を探しています。  
公式リファレンスによるとRuby2.7以降には、`Integer#[]` という非常に便利なメソッドがあり、

[code]

    i[nth, len] # (n >> i) & ((1 << len) - 1) と同じ 
    i[range]
    
[/code]

とすると、ビットを取り出すことができるそうです。

<https://docs.ruby-lang.org/ja/latest/method/Integer/i/=5b=5d.html>

一方で

> self[nth]=bit (つまりビットの修正) がないのは、Numeric 関連クラスが immutable であるためです。

という記載もあり、ビットを修正することができません。（Integerは変更できないので、新たにIntegerオブジェクトを作成しなければなりません）ここに記載されているビットの修正

[code]

    self[nth, len] = n
    
[/code]

に相当する操作はRubyでどう書けばよいでしょうか？

ウィキペディアの[マスク（情報工学）](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B9%E3%82%AF_\(%E6%83%85%E5%A0%B1%E5%B7%A5%E5%AD%A6\))の記事を参考に、次のように書いてみました。

[code]

    class Integer
      def []=(start, width, value)
        if value.bit_length > width
          # FIXME: valueが負の場合は少しエラーがおかしい…
          raise "Value #{value} is larger than #{(1 << width) - 1}"
        end
    
        all = ((1 << self.bit_length) - 1)
        mask = all ^ (((1 << width) - 1) << start)
        masked_value = self & mask
        new_value = masked_value | (value << start)
        p new_value
      end
    end
    
[/code]

私が思いついたやり方はこれですが、ほかにもっと良い方法があるかも知れません。ご存知の方は教えてください。また上記の実装方法の不備みたいなものがありましたら指摘して頂けると助かります。よろしくおねがいします。




とあるslackによると

[code]

    class Integer
      def bitset(start, width, value)
        mask = ~(~0 << width)
        (self & ~(mask << start)) | ((value & mask) << start)
      end
    end
    
[/code]

