Class: BinStruct::AbstractTLV Abstract
- Includes:
- Structable
- Defined in:
- lib/bin_struct/abstract_tlv.rb
Overview
Base class to define type-length-value data.
Usage
To simply define a new TLV class, do:
MyTLV = PacketGen::Types::AbstractTLV.create
MyTLV.define_type_enum 'one' => 1, 'two' => 2
This will define a new MyTLV
class, subclass of AbstractTLV. This class will define 3 attributes:
.define_type_enum
is, here, necessary to define enum hash to be used for #type
accessor, as this one is defined as an Enum.
This new defined class may now be easily used:
tlv = MyTLV.new(type: 1, value: 'abcd') # automagically set #length from value
tlv.type #=> 1
tlv.human_type #=> 'one'
tlv.length #=> 4
tlv.value #=> "abcd"
Advanced usage
Each attribute’s type may be changed at generating TLV class:
MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
length_class: PacketGen::Types::Int16,
value_class: PacketGen::Header::IP::Addr)
tlv = MyTLV.new(type: 1, value: '1.2.3.4')
tlv.type #=> 1
tlv.length #=> 4
tlv.value #=> '1.2.3.4'
tlv.to_s #=> "\x00\x01\x00\x04\x01\x02\x03\x04"
Some aliases may also be defined. For example, to create a TLV type whose type
attribute should be named code
:
MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
length_class: PacketGen::Types::Int16,
aliases: { code: :type })
tlv = MyTLV.new(code: 1, value: 'abcd')
tlv.code #=> 1
tlv.type #=> 1
tlv.length #=> 4
tlv.value #=> 'abcd'
Constant Summary collapse
- ATTR_TYPES =
{ 'T' => :type, 'L' => :length, 'V' => :value }.freeze
Constants inherited from Struct
Class Attribute Summary collapse
-
.aliases ⇒ Hash
Aliases defined in AbstractTLV.create.
- .attr_in_length ⇒ Object
-
.length ⇒ Integer
abstract
Length attribute for real TLV class.
-
.type ⇒ Integer
abstract
Type attribute for real TLV class.
-
.value ⇒ Object
abstract
Value attribute for real TLV class.
Instance Attribute Summary collapse
-
#length ⇒ Integer
abstract
Length attribute.
-
#type ⇒ Integer
abstract
Type attribute.
-
#value ⇒ Object
abstract
Value attribute.
Class Method Summary collapse
-
.create(type_class: Int8Enum, length_class: Int8, value_class: String, aliases: {}, attr_order: 'TLV', attr_in_length: 'V') ⇒ Class
Generate a TLV class.
-
.define_type_default(default) ⇒ void
abstract
Set default value for #type attribute.
-
.define_type_enum(hsh) ⇒ void
abstract
Set enum hash for #type attribute.
Instance Method Summary collapse
-
#calc_length ⇒ Integer
Calculate length.
-
#human_type ⇒ ::String
abstract
Get human-readable type.
-
#initialize(options = {}) ⇒ AbstractTLV
constructor
abstract
Return a new instance of a real TLV class.
-
#read(str) ⇒ AbstractTLV
abstract
Populate object from a binary string.
- #to_human ⇒ ::String abstract
Methods included from Structable
#format_inspect, #sz, #to_s, #type_name
Methods inherited from Struct
#[], #[]=, attributes, #attributes, #bits_on, define_attr, define_attr_after, define_attr_before, define_bit_attrs_on, inherited, #inspect, #offset_of, #optional?, #optional_attributes, #present?, remove_attr, remove_bit_attrs_on, #sz, #to_h, #to_s, update_attr
Constructor Details
#initialize(options = {}) ⇒ AbstractTLV
Should only be called on real TLV classes, created by create.
Return a new instance of a real TLV class.
192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/bin_struct/abstract_tlv.rb', line 192 def initialize( = {}) @attr_in_length = self.class.attr_in_length self.class.aliases.each do |al, orig| [orig] = [al] if .key?(al) end super # used #value= defined below, which set length if needed self.value = [:value] if [:value] calc_length unless .key?(:length) end |
Class Attribute Details
.aliases ⇒ Hash
Aliases defined in create
66 67 68 |
# File 'lib/bin_struct/abstract_tlv.rb', line 66 def aliases @aliases end |
.attr_in_length ⇒ Object
68 69 70 |
# File 'lib/bin_struct/abstract_tlv.rb', line 68 def attr_in_length @attr_in_length end |
.length ⇒ Integer
Length attribute for real TLV class
|
# File 'lib/bin_struct/abstract_tlv.rb', line 106
|
.type ⇒ Integer
Type attribute for real TLV class
|
# File 'lib/bin_struct/abstract_tlv.rb', line 106
|
.value ⇒ Object
Value attribute for real TLV class
|
# File 'lib/bin_struct/abstract_tlv.rb', line 106
|
Instance Attribute Details
#length ⇒ Integer
Length attribute
|
# File 'lib/bin_struct/abstract_tlv.rb', line 173
|
#type ⇒ Integer
Type attribute
|
# File 'lib/bin_struct/abstract_tlv.rb', line 173
|
#value ⇒ Object
Value attribute
|
# File 'lib/bin_struct/abstract_tlv.rb', line 173
|
Class Method Details
.create(type_class: Int8Enum, length_class: Int8, value_class: String, aliases: {}, attr_order: 'TLV', attr_in_length: 'V') ⇒ Class
Generate a TLV class
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/bin_struct/abstract_tlv.rb', line 80 def create(type_class: Int8Enum, length_class: Int8, value_class: String, aliases: {}, attr_order: 'TLV', attr_in_length: 'V') unless equal?(AbstractTLV) raise Error, '.create cannot be called on a subclass of PacketGen::Types::AbstractTLV' end klass = Class.new(self) klass.aliases = aliases klass.attr_in_length = attr_in_length check_attr_in_length(attr_in_length) check_attr_order(attr_order) generate_attributes(klass, attr_order, type_class, length_class, value_class) aliases.each do |al, orig| klass.instance_eval do alias_method al, orig if klass.method_defined?(orig) alias_method :"#{al}=", :"#{orig}=" if klass.method_defined?(:"#{orig}=") end end klass end |
.define_type_default(default) ⇒ void
132 133 134 |
# File 'lib/bin_struct/abstract_tlv.rb', line 132 def define_type_default(default) attr_defs[:type][:default] = default end |
.define_type_enum(hsh) ⇒ void
123 124 125 126 |
# File 'lib/bin_struct/abstract_tlv.rb', line 123 def define_type_enum(hsh) attr_defs[:type][:options][:enum].clear attr_defs[:type][:options][:enum].merge!(hsh) end |
Instance Method Details
#calc_length ⇒ Integer
Calculate length
253 254 255 256 257 258 259 260 261 |
# File 'lib/bin_struct/abstract_tlv.rb', line 253 def calc_length ail = @attr_in_length length = 0 ail.each_char do |attr_type| length += self[ATTR_TYPES[attr_type]].sz end self.length = length end |
#human_type ⇒ ::String
Should only be called on real TLV class instances.
Get human-readable type
240 241 242 |
# File 'lib/bin_struct/abstract_tlv.rb', line 240 def human_type self[:type].to_human.to_s end |
#read(str) ⇒ AbstractTLV
Should only be called on real TLV class instances.
Populate object from a binary string
208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/bin_struct/abstract_tlv.rb', line 208 def read(str) return self if str.nil? idx = 0 attributes.each do |attr_name| attr = self[attr_name] length = attr_name == :value ? real_length : attr.sz attr.read(str[idx, length]) idx += attr.sz end self end |
#to_human ⇒ ::String
Should only be called on real TLV class instances.
246 247 248 249 |
# File 'lib/bin_struct/abstract_tlv.rb', line 246 def to_human my_value = self[:value].is_a?(String) ? self[:value].inspect : self[:value].to_human 'type:%s,length:%u,value:%s' % [human_type, length, my_value] end |