C
Chuck Remes
While working on a problem this morning I came up with an interesting
technique for using the BitStruct gem to produce binary strings. After
some hacking around I discovered I didn't need to use BitStruct at
all. Even so I thought I would share what I learned so the technique
doesn't get lost.
Imagine you need to construct a binary string from some arbitrary
object. BitStruct allows you to do this in 3 ways: pass a binary
string directly, pass in a hash, or yield a block. It's easy to extend
this mechanism for parsing your own classes by building on the block
yield initialization mechanism.
hsh = {:a => 1, :b => "foo", :c => "bar"}
class C < BitStruct
signed :context, 32, "c id"
char assword, 12*8, "pw"
char :usr_name, 12*8, "name"
# important to initialize these values so the
# block passed to #super is evaluated correctly
initial_value.context = 0
initial_value.password = ''
initial_value.usr_name = ''
def initialize message
# parens on #super are important so no args
# are passed up to the parent; if this part fails
# then you missed
super() do |struct|
struct.context = message[:a]
struct.password = message[:b]
struct.usr_name = message[:c]
end
end
end
c = C.new hsh # very clean!
c.inspect
In this example I passed in a hash as my message, but the +message+
variable could have been any object that could be interrogated to
retrieve values for setting the bitstruct fields. I like this
technique because it delegates the responsibility of proper bitstruct
initialization to the class under construction. It nicely encapsulates
that operation which I believe demonstrates the Single Responsibility
principle.
I hope this is of use to someone someday.
cr
technique for using the BitStruct gem to produce binary strings. After
some hacking around I discovered I didn't need to use BitStruct at
all. Even so I thought I would share what I learned so the technique
doesn't get lost.
Imagine you need to construct a binary string from some arbitrary
object. BitStruct allows you to do this in 3 ways: pass a binary
string directly, pass in a hash, or yield a block. It's easy to extend
this mechanism for parsing your own classes by building on the block
yield initialization mechanism.
hsh = {:a => 1, :b => "foo", :c => "bar"}
class C < BitStruct
signed :context, 32, "c id"
char assword, 12*8, "pw"
char :usr_name, 12*8, "name"
# important to initialize these values so the
# block passed to #super is evaluated correctly
initial_value.context = 0
initial_value.password = ''
initial_value.usr_name = ''
def initialize message
# parens on #super are important so no args
# are passed up to the parent; if this part fails
# then you missed
super() do |struct|
struct.context = message[:a]
struct.password = message[:b]
struct.usr_name = message[:c]
end
end
end
c = C.new hsh # very clean!
c.inspect
In this example I passed in a hash as my message, but the +message+
variable could have been any object that could be interrogated to
retrieve values for setting the bitstruct fields. I like this
technique because it delegates the responsibility of proper bitstruct
initialization to the class under construction. It nicely encapsulates
that operation which I believe demonstrates the Single Responsibility
principle.
I hope this is of use to someone someday.
cr