Bit-twiddling with Ruby

I’ve always wanted to write some routines that help out with bit twiddling. Since I’m working on some byte level stuff recently (Smartcards, ISO7816 to be precise) I’ve finally gotten around to writing an API to make handling bytes easier and self-documenting. Basically, it’s a –attention buzzword– DSL for bitfield description. Not really gotten very far, but this is how it looks up to now: if you’ve got a byte composed of bits with the following semantics:

   |8|7|5|4|3|2|1|Desc
   ================================
   |1|-|-|-|-|-|-|Channel Encrypted
   |-|0|0|0|-|-|-|Method A
   |-|1|0|0|-|-|-|Method B
   |-|0|0|1|-|-|-|Method C
   |-|-|-|-|X|X|X|Channel Number 

I can use the following ruby code to represent it:

  require "bytes"
   b = Bytes::Byte.new "1......." => :enc,
                       ".000...." => :a,
                       ".100...." => :b,
                       ".001...." => :c,
                       ".....vvv" => :channel
   b.value = 0xff
   b.enc?        # true 
   b.b?          # false
   b.b           # `b.value` is now 0xCF / "11001111"
   b.b?          # true 
   b.channel     # 7
   b.channel = 0 # `b.value` is now 0xC8 / "11001000"

Instead of using the Byte class and instantiating it with the byte’s pattern, it’s also possible to include the module Bytes which adds a attr like class function (called byte_accessor) which adds the same sort of functionality to classes. Take this –vaguely contrived– implementation of the first two bytes of an IP Packet:

require "bytes_ng"
class IPPacket
  include Bytes
   byte_accessor :ver_ihl , "vvvv ...." => :version
                           ".... vvvv" => :ihl

   byte_accessor :tos, "111. .... | Precedence" => :network_control,
                       "110. ...."              => :inet_control,
                       "101. ...."              => :critic_epc,
                       "100. ...."              => :flash_override,
                       "011. ...."              => :flash,
                       "010. ...."              => :immediate,
                       "001. ...."              => :priority,
                       "000. ...."              => :routine,
                       "...0 .... | Delay"      => :normal_delay,
                       "...1 ...."              => :low_delay,
                       ".... 0... | Throughput" => :normal_throughput,
                       ".... 1..."              => :high_throughput,
                       ".... .0.. | Reliability"=> :low_reliability,
                       ".... .1.."              => :high_reliability,
                       ".... ..1. | RFU"        => :rfu_err_1
                       ".... ...1 | RFU"        => :rfu_err_2
end

This adds two instance variables (and their respective accessors) named ver_ihl and tos to the class IPPacket. These contain the actual byte value. It also adds a bunch of methods (like in the example above) that can be used to query and set the individual bits.

I’ve not gotten around to properly releasing it yet, but it works quite well so far. In case you’re interested, you can currently get it here.

Future plans are to package it and (maybe) add multi-byte functionality.

Kommentieren ist momentan nicht möglich.