Class: BitStruct
- Inherits:
-
String
- Object
- String
- BitStruct
- Defined in:
- lib/bit-struct/bit-struct.rb,
lib/bit-struct/yaml.rb,
lib/bit-struct/fields.rb,
lib/bit-struct/pad-field.rb,
lib/bit-struct/char-field.rb,
lib/bit-struct/text-field.rb,
lib/bit-struct/float-field.rb,
lib/bit-struct/octet-field.rb,
lib/bit-struct/nested-field.rb,
lib/bit-struct/signed-field.rb,
lib/bit-struct/vector-field.rb,
lib/bit-struct/unsigned-field.rb,
lib/bit-struct/hex-octet-field.rb
Overview
Class for packed binary data, with defined bitfields and accessors for them. See intro.txt for an overview.
Data after the end of the defined fields is accessible using the rest
declaration. See examples/ip.rb. Nested fields can be declared using nest
. See examples/nest.rb.
Note that all string methods are still available: length, grep, etc. The String#replace method is useful.
Defined Under Namespace
Classes: CharField, ClosedClassError, Field, FieldNameError, FloatField, HexOctetField, NestedField, OctetField, PadField, SignedField, TextField, UnsignedField, Vector, VectorField
Constant Summary collapse
- VERSION =
"0.13.5"
- NULL_FIELD =
Field.new(0, 0, :null, :display_name => "null field")
- DESCRIBE_FORMAT =
Default format for describe. Fields are byte, type, name, size, and description.
"%8s: %-12s %-14s[%4s] %s"
- DEFAULT_TO_H_OPTS =
{ :convert_keys => :to_sym, :include_rest => true }
- DEFAULT_INSPECT_OPTS =
:section: inspection methods
{ :format => "#<%s %s>", :field_format => "%s=%s", :separator => ", ", :field_name_meth => :name, :include_rest => true, :brackets => ["[", "]"], :include_class => true, :simple_format => "<%s>" }
- DETAILED_INSPECT_OPTS =
{ :format => "%s:\n%s", :field_format => "%30s = %s", :separator => "\n", :field_name_meth => :display_name, :include_rest => true, :brackets => [nil, "\n"], :include_class => true, :simple_format => "\n%s" }
Class Method Summary collapse
-
.add_field(name, length, opts = {}) ⇒ Object
Add a field to the BitStruct (usually, this is only used internally).
-
.bit_length ⇒ Object
Length, in bits, of this object.
-
.char(name, length, *rest) ⇒ Object
(also: string)
Define a char string field in the current subclass of BitStruct, with the given name and length (in bits).
-
.closed! ⇒ Object
:nodoc:.
-
.default_options(h = nil) ⇒ Object
Get or set the hash of default options for the class, which apply to all fields.
-
.describe(fmt = nil, opts = {}) ⇒ Object
Textually describe the fields of this class of BitStructs.
-
.describe_format ⇒ Object
Can be overridden to use a different format.
- .field_by_name(name) ⇒ Object
-
.fields ⇒ Object
Return the list of fields for this class.
-
.float(name, length, *rest) ⇒ Object
Define a floating point field in the current subclass of BitStruct, with the given name and length (in bits).
-
.hex_octets(name, length, *rest) ⇒ Object
Define an octet string field in the current subclass of BitStruct, with the given name and length (in bits).
- .inherited(cl) ⇒ Object
-
.initial_value {|@initial_value| ... } ⇒ Object
The unique “prototype” object from which new instances are copied.
-
.join(*structs) ⇒ Object
Join the given structs (array or multiple args) as a string.
-
.nest(name, *rest, &block) ⇒ Object
(also: struct)
Define a nested field in the current subclass of BitStruct, with the given name and nested_class.
-
.note(*str) ⇒ Object
Subclasses can use this to append a string (or several) to the #describe output.
-
.octets(name, length, *rest) ⇒ Object
Define an octet string field in the current subclass of BitStruct, with the given name and length (in bits).
-
.own_fields ⇒ Object
Return the list of fields defined by this class, not inherited from the superclass.
-
.pad(name, length, *rest) ⇒ Object
(also: padding)
Define a padding field in the current subclass of BitStruct, with the given name and length (in bits).
-
.parse(data, *classes) ⇒ Object
Take
data
(a string or BitStruct) and parse it into instances of theclasses
, returning them in an array. -
.parse_options(ary, default_name, default_field_class) ⇒ Object
:nodoc:.
-
.rest(name, *ary) ⇒ Object
Define accessors for a variable length substring from the end of the defined fields to the end of the BitStruct.
-
.rest_field ⇒ Object
Not included with the other fields, but accessible separately.
-
.round_byte_length ⇒ Object
Length, in bytes (rounded up), of this object.
-
.signed(name, length, *rest) ⇒ Object
Define a signed integer field in the current subclass of BitStruct, with the given name and length (in bits).
-
.text(name, length, *rest) ⇒ Object
Define a printable text string field in the current subclass of BitStruct, with the given name and length (in bits).
-
.unsigned(name, length, *rest) ⇒ Object
Define a unsigned integer field in the current subclass of BitStruct, with the given name and length (in bits).
-
.vector(name, *rest, &block) ⇒ Object
Define a vector field in the current subclass of BitStruct, with the given name.
-
.yaml_new(klass, tag, val) ⇒ Object
:nodoc:.
Instance Method Summary collapse
- #[](*args) ⇒ Object
- #[]=(*args) ⇒ Object
-
#field_by_name(name) ⇒ Object
Return the field with the given name.
-
#fields ⇒ Object
Return the list of fields for this class.
-
#initialize(value = nil) {|_self| ... } ⇒ BitStruct
constructor
Initialize the string with the given string or bitstruct, or with a hash of field=>value pairs, or with the defaults for the BitStruct subclass, or with an IO or other object with a #read method.
-
#inspect(opts = DEFAULT_INSPECT_OPTS) ⇒ Object
A standard inspect method which does not add newlines.
-
#inspect_detailed ⇒ Object
A more visually appealing inspect method that puts each field/value on a separate line.
-
#is_complex_yaml? ⇒ Boolean
:nodoc:.
-
#to_a(include_rest = true) ⇒ Object
Returns an array of values of the fields of the BitStruct.
-
#to_h(opts = DEFAULT_TO_H_OPTS) ⇒ Object
Returns a hash of name=>value,… for each field.
-
#to_yaml(opts = {}) ⇒ Object
Return YAML representation of the BitStruct.
-
#to_yaml_properties ⇒ Object
:nodoc:.
-
#to_yaml_type ⇒ Object
:nodoc:.
Constructor Details
#initialize(value = nil) {|_self| ... } ⇒ BitStruct
Initialize the string with the given string or bitstruct, or with a hash of field=>value pairs, or with the defaults for the BitStruct subclass, or with an IO or other object with a #read method. Fields can be strings or symbols. Finally, if a block is given, yield the instance for modification using accessors.
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'lib/bit-struct/bit-struct.rb', line 329 def initialize(value = nil) # :yields: instance self << self.class.initial_value case value when Hash value.each do |k, v| send "#{k}=", v end when nil else if value.respond_to?(:read) value = value.read(self.class.round_byte_length) end self[0, value.length] = value end self.class.closed! yield self if block_given? end |
Class Method Details
.add_field(name, length, opts = {}) ⇒ Object
Add a field to the BitStruct (usually, this is only used internally).
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/bit-struct/bit-struct.rb', line 150 def add_field(name, length, opts = {}) round_byte_length ## just to make sure this has been calculated ## before adding anything name = name.to_sym if @closed raise ClosedClassError, "Cannot add field #{name}: " + "The definition of the #{self.inspect} BitStruct class is closed." end if fields.find {|f|f.name == name} raise FieldNameError, "Field #{name} is already defined as a field." end if instance_methods(true).find {|m| m == name} if opts[:allow_method_conflict] || opts["allow_method_conflict"] warn "Field #{name} is already defined as a method." else raise FieldNameError,"Field #{name} is already defined as a method." end end field_class = opts[:field_class] prev = fields[-1] || NULL_FIELD offset = prev.offset + prev.length field = field_class.new(offset, length, name, opts) field.add_accessors_to(self) fields << field own_fields << field @bit_length += field.length @round_byte_length = (bit_length/8.0).ceil if @initial_value diff = @round_byte_length - @initial_value.length if diff > 0 @initial_value << "\0" * diff end end field end |
.bit_length ⇒ Object
Length, in bits, of this object.
219 220 221 |
# File 'lib/bit-struct/bit-struct.rb', line 219 def bit_length @bit_length ||= fields.inject(0) {|a, f| a + f.length} end |
.char(name, length, *rest) ⇒ Object Also known as: string
Define a char string field in the current subclass of BitStruct, with the given name and length (in bits). Trailing nulls are considered part of the string.
If a class is provided, use it for the Field class. If a string is provided, use it for the display_name. If a hash is provided, use it for options.
Note that the accessors have COPY semantics, not reference.
13 14 15 16 |
# File 'lib/bit-struct/fields.rb', line 13 def char(name, length, *rest) opts = (rest, name, CharField) add_field(name, length, opts) end |
.closed! ⇒ Object
:nodoc:
228 229 230 |
# File 'lib/bit-struct/bit-struct.rb', line 228 def closed! # :nodoc: @closed = true end |
.default_options(h = nil) ⇒ Object
Get or set the hash of default options for the class, which apply to all fields. Changes take effect immediately, so can be used alternatingly with blocks of field declarations. If h
is provided, update the default options with that hash. Default options are inherited.
This is especially useful with the :endian => val
option.
210 211 212 213 214 215 216 |
# File 'lib/bit-struct/bit-struct.rb', line 210 def h = nil @default_options ||= superclass..dup if h @default_options.merge! h end @default_options end |
.describe(fmt = nil, opts = {}) ⇒ Object
Textually describe the fields of this class of BitStructs. Returns a printable table (array of line strings), based on fmt
, which defaults to #describe_format, which defaults to DESCRIBE_FORMAT
.
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/bit-struct/bit-struct.rb', line 273 def describe(fmt = nil, opts = {}) if fmt.kind_of? Hash opts = fmt; fmt = nil end if block_given? fields.each do |field| field.describe(opts) do |desc| yield desc end end nil else fmt ||= describe_format result = [] unless opts[:omit_header] result << fmt % ["byte", "type", "name", "size", "description"] result << "-"*70 end fields.each do |field| field.describe(opts) do |desc| result << fmt % desc end end unless opts[:omit_footer] result << @note if @note end result end end |
.describe_format ⇒ Object
Can be overridden to use a different format.
266 267 268 |
# File 'lib/bit-struct/bit-struct.rb', line 266 def describe_format DESCRIBE_FORMAT end |
.field_by_name(name) ⇒ Object
232 233 234 235 236 237 238 239 240 |
# File 'lib/bit-struct/bit-struct.rb', line 232 def field_by_name name @field_by_name ||= {} field = @field_by_name[name] unless field field = fields.find {|f| f.name == name} @field_by_name[name] = field if field end field end |
.fields ⇒ Object
Return the list of fields for this class.
139 140 141 |
# File 'lib/bit-struct/bit-struct.rb', line 139 def fields @fields ||= self == BitStruct ? [] : superclass.fields.dup end |
.float(name, length, *rest) ⇒ Object
Define a floating point field in the current subclass of BitStruct, with the given name and length (in bits).
If a class is provided, use it for the Field class. If a string is provided, use it for the display_name. If a hash is provided, use it for options.
The :endian => :native
option overrides the default of :network
byte ordering, in favor of native byte ordering. Also permitted are :big
(same as :network
) and :little
.
32 33 34 35 |
# File 'lib/bit-struct/fields.rb', line 32 def float name, length, *rest opts = (rest, name, FloatField) add_field(name, length, opts) end |
.hex_octets(name, length, *rest) ⇒ Object
Define an octet string field in the current subclass of BitStruct, with the given name and length (in bits). Trailing nulls are not considered part of the string. The field is accessed using period-separated hex digits.
If a class is provided, use it for the Field class. If a string is provided, use it for the display_name. If a hash is provided, use it for options.
47 48 49 50 |
# File 'lib/bit-struct/fields.rb', line 47 def hex_octets(name, length, *rest) opts = (rest, name, HexOctetField) add_field(name, length, opts) end |
.inherited(cl) ⇒ Object
122 123 124 125 126 127 128 129 |
# File 'lib/bit-struct/bit-struct.rb', line 122 def inherited cl cl.instance_eval do @initial_value = nil @closed = nil @rest_field = nil @note = nil end end |
.initial_value {|@initial_value| ... } ⇒ Object
The unique “prototype” object from which new instances are copied. The fields of this instance can be modified in the class definition to set default values for the fields in that class. (Otherwise, defaults defined by the fields themselves are used.) A copy of this object is inherited in subclasses, which they may override using defaults and by writing to the initial_value object itself.
If called with a block, yield the initial value object before returning it. Useful for customization within a class definition.
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/bit-struct/bit-struct.rb', line 418 def initial_value # :yields: the initial value unless @initial_value iv = defined?(superclass.initial_value) ? superclass.initial_value.dup : "" if iv.length < round_byte_length iv << "\0" * (round_byte_length - iv.length) end @initial_value = "" # Serves as initval while the real initval is inited @initial_value = new(iv) @closed = false # only creating the first _real_ instance closes. fields.each do |field| @initial_value.send("#{field.name}=", field.default) if field.default end end yield @initial_value if block_given? @initial_value end |
.join(*structs) ⇒ Object
Join the given structs (array or multiple args) as a string. Actually, the inherited String#+ instance method is the same, as is using Array#join.
451 452 453 |
# File 'lib/bit-struct/bit-struct.rb', line 451 def join(*structs) structs.flatten.map {|struct| struct.to_s}.join("") end |
.nest(name, *rest, &block) ⇒ Object Also known as: struct
Define a nested field in the current subclass of BitStruct, with the given name and nested_class. Length is determined from nested_class.
If a class is provided, use it for the Field class (i.e. <=NestedField). If a string is provided, use it for the display_name. If a hash is provided, use it for options.
For example:
class Sub < BitStruct
unsigned :x, 8
end
class A < BitStruct
nest :n, Sub
end
a = A.new
p a # ==> #<A n=#<Sub x=0>>
If a block is given, use it to define the nested fields. For example, the following is equivalent to the above example:
class A < BitStruct
nest :n do
unsigned :x, 8
end
end
WARNING: the accessors have COPY semantics, not reference. When you call a reader method to get the nested structure, you get a copy of that data. Expressed in terms of the examples above:
# This fails to set x in a.
a.n.x = 3
p a # ==> #<A n=#<Sub x=0>>
# This works
n = a.n
n.x = 3
a.n = n
p a # ==> #<A n=#<Sub x=3>>
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/bit-struct/fields.rb', line 98 def nest(name, *rest, &block) nested_class = rest.grep(Class).find {|cl| cl <= BitStruct} rest.delete nested_class opts = (rest, name, NestedField) nested_class = opts[:nested_class] ||= nested_class unless (block and not nested_class) or (nested_class and not block) raise ArgumentError, "nested field must have either a nested_class option or a block," + " but not both" end unless nested_class nested_class = Class.new(BitStruct) nested_class.class_eval(&block) end opts[:default] ||= nested_class.initial_value.dup opts[:nested_class] = nested_class field = add_field(name, nested_class.bit_length, opts) field end |
.note(*str) ⇒ Object
Subclasses can use this to append a string (or several) to the #describe output. Notes are not cumulative with inheritance. When used with no arguments simply returns the note string
313 314 315 316 |
# File 'lib/bit-struct/bit-struct.rb', line 313 def note(*str) @note = str unless str.empty? @note end |
.octets(name, length, *rest) ⇒ Object
Define an octet string field in the current subclass of BitStruct, with the given name and length (in bits). Trailing nulls are not considered part of the string. The field is accessed using period-separated decimal digits.
If a class is provided, use it for the Field class. If a string is provided, use it for the display_name. If a hash is provided, use it for options.
132 133 134 135 |
# File 'lib/bit-struct/fields.rb', line 132 def octets(name, length, *rest) opts = (rest, name, OctetField) add_field(name, length, opts) end |
.own_fields ⇒ Object
Return the list of fields defined by this class, not inherited from the superclass.
145 146 147 |
# File 'lib/bit-struct/bit-struct.rb', line 145 def own_fields @own_fields ||= [] end |
.pad(name, length, *rest) ⇒ Object Also known as: padding
Define a padding field in the current subclass of BitStruct, with the given name and length (in bits).
If a class is provided, use it for the Field class. If a string is provided, use it for the display_name. If a hash is provided, use it for options.
145 146 147 148 |
# File 'lib/bit-struct/fields.rb', line 145 def pad(name, length, *rest) opts = (rest, name, PadField) add_field(name, length, opts) end |
.parse(data, *classes) ⇒ Object
Take data
(a string or BitStruct) and parse it into instances of the classes
, returning them in an array. The classes can be given as an array or a separate arguments. (For parsing a string into a single BitStruct instance, just use the #new method with the string as an arg.)
442 443 444 445 446 |
# File 'lib/bit-struct/bit-struct.rb', line 442 def parse(data, *classes) classes.flatten.map do |c| c.new(data.slice!(0...c.round_byte_length)) end end |
.parse_options(ary, default_name, default_field_class) ⇒ Object
:nodoc:
194 195 196 197 198 199 200 201 202 |
# File 'lib/bit-struct/bit-struct.rb', line 194 def (ary, default_name, default_field_class) # :nodoc: opts = ary.grep(Hash).first || {} opts = .merge(opts) opts[:display_name] = ary.grep(String).first || default_name opts[:field_class] = ary.grep(Class).first || default_field_class opts end |
.rest(name, *ary) ⇒ Object
Define accessors for a variable length substring from the end of the defined fields to the end of the BitStruct. The rest may behave as a String or as some other String or BitStruct subclass.
This does not add a field, which is useful because a superclass can have a rest method which accesses subclass data. In particular, #rest does not affect the #round_byte_length class method. Of course, any data in rest does add to the #length of the BitStruct, calculated as a string. Also, rest is not inherited.
The ary
argument(s) work as follows:
If a class is provided, use it for the Field class (String by default). If a string is provided, use it for the display_name (name
by default). If a hash is provided, use it for options.
Warning: the rest reader method returns a copy of the field, so accessors on that returned value do not affect the original rest field.
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 |
# File 'lib/bit-struct/bit-struct.rb', line 541 def self.rest(name, *ary) if @rest_field raise ArgumentError, "Duplicate rest field: #{name.inspect}." end opts = (ary, name, String) offset = round_byte_length byte_range = offset..-1 class_eval do field_class = opts[:field_class] define_method name do || field_class.new(self[byte_range]) end define_method "#{name}=" do |val| self[byte_range] = val end @rest_field = Field.new(offset, -1, name, { :display_name => opts[:display_name], :rest_class => field_class }) end end |
.rest_field ⇒ Object
Not included with the other fields, but accessible separately.
567 |
# File 'lib/bit-struct/bit-struct.rb', line 567 def self.rest_field; @rest_field; end |
.round_byte_length ⇒ Object
Length, in bytes (rounded up), of this object.
224 225 226 |
# File 'lib/bit-struct/bit-struct.rb', line 224 def round_byte_length @round_byte_length ||= (bit_length/8.0).ceil end |
.signed(name, length, *rest) ⇒ Object
Define a signed integer field in the current subclass of BitStruct, with the given name and length (in bits).
If a class is provided, use it for the Field class. If a string is provided, use it for the display_name. If a hash is provided, use it for options.
SignedField adds the :fixed => divisor
option, which specifies that the internally stored value is interpreted as a fixed point real number with the specified divisor
.
The :endian => :native
option overrides the default of :network
byte ordering, in favor of native byte ordering. Also permitted are :big
(same as :network
) and :little
.
168 169 170 171 |
# File 'lib/bit-struct/fields.rb', line 168 def signed name, length, *rest opts = (rest, name, SignedField) add_field(name, length, opts) end |
.text(name, length, *rest) ⇒ Object
Define a printable text string field in the current subclass of BitStruct, with the given name and length (in bits). Trailing nulls are not considered part of the string.
If a class is provided, use it for the Field class. If a string is provided, use it for the display_name. If a hash is provided, use it for options.
Note that the accessors have COPY semantics, not reference.
184 185 186 187 |
# File 'lib/bit-struct/fields.rb', line 184 def text(name, length, *rest) opts = (rest, name, TextField) add_field(name, length, opts) end |
.unsigned(name, length, *rest) ⇒ Object
Define a unsigned integer field in the current subclass of BitStruct, with the given name and length (in bits).
If a class is provided, use it for the Field class. If a string is provided, use it for the display_name. If a hash is provided, use it for options.
UnsignedField adds the :fixed => divisor
option, which specifies that the internally stored value is interpreted as a fixed point real number with the specified divisor
.
The :endian => :native
option overrides the default of :network
byte ordering, in favor of native byte ordering. Also permitted are :big
(same as :network
) and :little
.
206 207 208 209 |
# File 'lib/bit-struct/fields.rb', line 206 def unsigned name, length, *rest opts = (rest, name, UnsignedField) add_field(name, length, opts) end |
.vector(name, *rest, &block) ⇒ Object
Define a vector field in the current subclass of BitStruct, with the given name.
If a class is provided, use it for the Vector class, otherwise the block must define the entry fields. The two forms looks like this:
class Vec < BitStruct::Vector
# these declarations apply to *each* entry in the vector:
unsigned :x, 16
signed :y, 32
end
class Packet < BitStruct
# Using the Vec class defined above
vector :v, Vec, "a vector", :length => 5
# equivalently, using an anonymous subclass of BitStruct::Vector
vector :v2, "a vector", :length => 5 do
unsigned :x, 16
signed :y, 32
end
end
If a string is provided, use it for the display_name. If a hash is provided, use it for options. If a number is provided, use it for length (equivalent to using the :length option).
WARNING: the accessors have COPY semantics, not reference. When you call a reader method to get the vector structure, you get a copy of that data.
For example, to modify the numeric fields in a Packet as defined above:
pkt = Packet.new
vec = pkt.v
entry = vec[2]
entry.x = 123
entry.y = -456
vec[2] = entry
pkt.v = vec
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/bit-struct/fields.rb', line 254 def vector(name, *rest, &block) opts = (rest, name, nil) cl = opts[:field_class] opts[:field_class] = VectorField unless (block and not cl) or (cl and not block) raise ArgumentError, "vector must have either a class or a block, but not both" end case when cl == nil vector_class = Class.new(BitStruct::Vector) vector_class.class_eval(&block) when cl < BitStruct vector_class = Class.new(BitStruct::Vector) vector_class.struct_class cl when cl < BitStruct::Vector vector_class = cl else raise ArgumentError, "Bad vector class: #{cl.inspect}" end vector_class. length = opts[:length] || rest.grep(Integer).first ## what about :length => :lenfield unless length raise ArgumentError, "Must provide length as argument N or as option :length => N" end opts[:default] ||= vector_class.new(length) ## nil if variable length opts[:vector_class] = vector_class bit_length = vector_class.struct_class.round_byte_length * 8 * length field = add_field(name, bit_length, opts) field end |
.yaml_new(klass, tag, val) ⇒ Object
:nodoc:
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/bit-struct/yaml.rb', line 53 def self.yaml_new( klass, tag, val ) # :nodoc: unless Hash === val raise YAML::TypeError, "Invalid BitStruct: " + val.inspect end bitstruct_name, bitstruct_type = YAML.read_type_class( tag, BitStruct ) st = bitstruct_type.new val.each do |k,v| st.send( "#{k}=", v ) end st end |
Instance Method Details
#[](*args) ⇒ Object
390 391 392 393 394 395 396 |
# File 'lib/bit-struct/bit-struct.rb', line 390 def [](*args) if args.size == 1 and args[0].kind_of?(Fixnum) super.ord else super end end |
#[]=(*args) ⇒ Object
398 399 400 401 402 403 404 |
# File 'lib/bit-struct/bit-struct.rb', line 398 def []=(*args) if args.size == 2 and (i=args[0]).kind_of?(Fixnum) super(i, args[1].chr) else super end end |
#field_by_name(name) ⇒ Object
Return the field with the given name.
249 250 251 |
# File 'lib/bit-struct/bit-struct.rb', line 249 def field_by_name name self.class.field_by_name name end |
#fields ⇒ Object
Return the list of fields for this class.
244 245 246 |
# File 'lib/bit-struct/bit-struct.rb', line 244 def fields self.class.fields end |
#inspect(opts = DEFAULT_INSPECT_OPTS) ⇒ Object
A standard inspect method which does not add newlines.
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 |
# File 'lib/bit-struct/bit-struct.rb', line 484 def inspect(opts = DEFAULT_INSPECT_OPTS) field_format = opts[:field_format] field_name_meth = opts[:field_name_meth] fields_for_inspect = fields.select {|field| field.inspectable?} if opts[:include_rest] and (rest_field = self.class.rest_field) fields_for_inspect << rest_field end ary = fields_for_inspect.map do |field| field_format % [field.send(field_name_meth), field.inspect_in_object(self, opts)] end body = ary.join(opts[:separator]) if opts[:include_class] opts[:format] % [self.class, body] else opts[:simple_format] % body end end |
#inspect_detailed ⇒ Object
A more visually appealing inspect method that puts each field/value on a separate line. Very useful when output is scrolling by on a screen.
(This is actually a convenience method to call #inspect with the DETAILED_INSPECT_OPTS opts.)
513 514 515 |
# File 'lib/bit-struct/bit-struct.rb', line 513 def inspect_detailed inspect(DETAILED_INSPECT_OPTS) end |
#is_complex_yaml? ⇒ Boolean
:nodoc:
5 6 7 |
# File 'lib/bit-struct/yaml.rb', line 5 def is_complex_yaml? # :nodoc: true end |
#to_a(include_rest = true) ⇒ Object
Returns an array of values of the fields of the BitStruct. By default, include the rest field.
377 378 379 380 381 382 383 384 385 386 |
# File 'lib/bit-struct/bit-struct.rb', line 377 def to_a(include_rest = true) ary = fields.map do |f| send(f.name) end if include_rest and (rest_field = self.class.rest_field) ary << send(rest_field.name) end end |
#to_h(opts = DEFAULT_TO_H_OPTS) ⇒ Object
Returns a hash of name=>value,… for each field. By default, include the rest field. Keys are symbols derived from field names using to_sym
, unless <tt>opts<tt> is set to some other method name.
361 362 363 364 365 366 367 368 369 370 371 372 373 |
# File 'lib/bit-struct/bit-struct.rb', line 361 def to_h(opts = DEFAULT_TO_H_OPTS) converter = opts[:convert_keys] || :to_sym fields_for_to_h = fields if opts[:include_rest] and (rest_field = self.class.rest_field) fields_for_to_h += [rest_field] end fields_for_to_h.inject({}) do |h,f| h[f.name.send(converter)] = send(f.name) h end end |
#to_yaml(opts = {}) ⇒ Object
Return YAML representation of the BitStruct.
18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/bit-struct/yaml.rb', line 18 def to_yaml( opts = {} ) # :nodoc: opts[:DocType] = self.class if Hash === opts YAML.quick_emit(self.object_id, opts) do |out| out.map(to_yaml_type) do |map| fields.each do |field| fn = field.name map.add(fn, send(fn)) end end end end |
#to_yaml_properties ⇒ Object
:nodoc:
33 34 35 36 37 38 39 40 |
# File 'lib/bit-struct/yaml.rb', line 33 def to_yaml_properties # :nodoc: yaml_fields = fields.select {|field| field.inspectable?} props = yaml_fields.map {|f| f.name.to_s} if (rest_field = self.class.rest_field) props << rest_field.name.to_s end props end |
#to_yaml_type ⇒ Object
:nodoc:
14 15 16 |
# File 'lib/bit-struct/yaml.rb', line 14 def to_yaml_type # :nodoc: "!ruby/bitstruct:#{self.class}" end |