BitStruct technique

Discussion in 'Ruby' started by Chuck Remes, May 14, 2009.

  1. Chuck Remes

    Chuck Remes Guest

    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 :password, 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
     
    Chuck Remes, May 14, 2009
    #1
    1. Advertising

  2. Chuck Remes wrote:
    > 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]


    If you add this line here:

    yield struct if block_given?

    then the block initialization can still be used by subclasses or by the
    caller of #new:

    c = C.new hsh do |struct|
    struct.context = 2
    end

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, May 14, 2009
    #2
    1. Advertising

  3. Chuck Remes wrote:
    > 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 :password, 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


    I think I see where you're going with that, but just so others know, the
    hash-based initialization is simple (though it does require that the
    hash keys match the field names--and avoiding this is probably the point
    of your code):

    require 'bit-struct'

    hsh = { :context => 1, :password => "foo", :usr_name => "bar" }

    class C < BitStruct
    signed :context, 32, "c id"
    char :password, 12*8, "pw"
    char :usr_name, 12*8, "name"
    end

    c = C.new hsh

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, May 14, 2009
    #3
  4. Chuck Remes

    Chuck Remes Guest

    On May 14, 2009, at 4:53 PM, Joel VanderWerf wrote:

    > Chuck Remes wrote:
    >>


    >> 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

    >
    > I think I see where you're going with that, but just so others know,
    > the hash-based initialization is simple (though it does require that
    > the hash keys match the field names--and avoiding this is probably
    > the point of your code):
    >
    > require 'bit-struct'
    >
    > hsh = { :context => 1, :password => "foo", :usr_name => "bar" }
    >
    > class C < BitStruct
    > signed :context, 32, "c id"
    > char :password, 12*8, "pw"
    > char :usr_name, 12*8, "name"
    > end
    >
    > c = C.new hsh


    Joel,

    that's right. I probably shouldn't have used a hash as my example
    since you already have hash-based initialization built in. I meant for
    this to be a nice way to pass an arbitrary object to the constructor
    so the logic of getting data from that object would be encapsulated in
    one spot. I also could have built a temporary hash from the object
    argument and passed that to the superclass' constructor but I prefer
    the block-based initialization for readability.

    And thanks for creating such a neat library. I don't have a need for
    it now that I understand my problem domain better, but rest assured it
    is now a member of my toolbox for some future problem when I do need it.

    cr
     
    Chuck Remes, May 16, 2009
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Weng Tianxiang
    Replies:
    4
    Views:
    3,150
    Weng Tianxiang
    Apr 7, 2005
  2. Dave Swersky

    ASP.NET Technique Headcheck

    Dave Swersky, Aug 13, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    343
    Dave Swersky
    Aug 13, 2003
  3. Jim Heavey

    Best Technique

    Jim Heavey, Nov 11, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    370
    Jim Heavey
    Nov 11, 2003
  4. Joel VanderWerf

    [ANN] BitStruct

    Joel VanderWerf, Oct 10, 2005, in forum: Ruby
    Replies:
    3
    Views:
    244
    Joel VanderWerf
    Oct 18, 2005
  5. Jaikanth Krishnaswamy

    BitStruct-28bit-Ruby Beginner

    Jaikanth Krishnaswamy, Nov 22, 2010, in forum: Ruby
    Replies:
    3
    Views:
    236
    Michael Bruschkewitz
    Dec 2, 2010
Loading...

Share This Page