From: Joel VanderWerf Date: 2005-10-10T08:51:59+09:00 Subject: [ANN] BitStruct (Exerpt from the docs at the project page, http://redshift.sourceforge.net/bit-struct/.) = BitStruct Class for packed binary data stored in ruby Strings. BitStruct accessors, generated from user declared fields, use pack/unpack to treat substrings as fields with a specified portable format. Field types include * signed and unsigned integer (1..8 bits, or 16 or 32 bits) * fixed point, with arbitrary scale factor * fixed length character array * null-terminated character array for printable text * octets (hex and decimal representation options; useful for IP and MAC addrs) * float * nested BitStruct * free-form "rest" field (e.g., for the variable-size payload of a packet) == Uses BitStruct is useful for defining packets used in network protocols. This is especially useful for raw IP--see examples/ping-recv.rb. All multibyte numeric fields are stored in network order (though this could be different for user-defined field classes). BitStruct is most efficient when your data is primarily treated as a binary string, and only secondarily treated as a data structure. (For instance, you are routing packets from one socket to another, possibly looking at one or two fields as it passes through or munging some headers.) If accessor operations are a bottleneck, a better approach is to define a class that wraps an array and uses pack/unpack when the object needs to behave like a binary string. == Example An IP packet can be defined and used like this: require 'bit-struct' class IP < BitStruct unsigned :ip_v, 4, "Version" unsigned :ip_hl, 4, "Header length" unsigned :ip_tos, 8, "TOS" unsigned :ip_len, 16, "Length" unsigned :ip_id, 16, "ID" unsigned :ip_off, 16, "Frag offset" unsigned :ip_ttl, 8, "TTL" unsigned :ip_p, 8, "Protocol" unsigned :ip_sum, 16, "Checksum" octets :ip_src, 32, "Source addr" octets :ip_dst, 32, "Dest addr" rest :body, "Body of message" note " rest is application defined message body" initial_value.ip_v = 4 initial_value.ip_hl = 5 end ip = IP.new ip.ip_tos = 0 ip.ip_len = 0 ip.ip_id = 0 ip.ip_off = 0 ip.ip_ttl = 255 ip.ip_p = 255 ip.ip_sum = 0 ip.ip_src = "192.168.1.4" ip.ip_dst = "192.168.1.255" ip.body = "This is the payload text." ip.ip_len = ip.length puts ip.inspect puts "-"*50 puts ip.inspect_detailed puts "-"*50 puts ip.body puts "-"*50 puts IP.describe (Note that you can also construct an IP packet by passing a string to new, or by passing a hash of field,value pairs, or by providing a block that is yielded the new BitStruct.) The output of this fragment is: # -------------------------------------------------- IP: Version = 4 Header length = 5 TOS = 0 Length = 45 ID = 0 Frag offset = 0 TTL = 255 Protocol = 255 Checksum = 0 Source addr = "192.168.1.4" Dest addr = "192.168.1.255" -------------------------------------------------- This is the payload text. -------------------------------------------------- Description of IP Packet: byte: type name [size] description ---------------------------------------------------------------------- @0: unsigned ip_v [ 4b] Version @0: unsigned ip_hl [ 4b] Header length @1: unsigned ip_tos [ 8b] TOS @2: unsigned ip_len [ 16b] Length @4: unsigned ip_id [ 16b] ID @6: unsigned ip_off [ 16b] Frag offset @8: unsigned ip_ttl [ 8b] TTL @9: unsigned ip_p [ 8b] Protocol @10: unsigned ip_sum [ 16b] Checksum @12: octets ip_src [ 32b] Source addr @16: octets ip_dst [ 32b] Dest addr rest is application defined message body -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407