class PacketGen::Types::TLV
Class to handle Type-Length-Value attributes
TLV
fields handles three subfields:
-
a tag/type field (defaults: {Int8} type),
-
a length field (defaults: {Int8} type),
-
a value field (defaults: {String} type).
{#initialize} supports options to change tag and length type. By example, to declare a TLV
using {Int16}:
define_field :tlv, PacketGen::Types::TLV, builder: ->(obj) { PacketGen::Types::TLV.new(t: PacketGen::Types::Int16, l: PacketGen::Types::Int16) }
Subclasses¶ ↑
A subclass may defined a constant hash TYPES. This hash defines human readable types versus their integer values. Hash keys are integer values, and hash values are types as strings.
If TYPES is defined, a subclass may:
-
print human readable type using {#human_type},
-
set type as
String
with {#type=}.
@author Sylvain Daubert @deprecated Use {AbstractTLV} instead. @since 3.1.0 deprecated
Public Class Methods
@param [Hash] options @option options [Integer] :type @option options [Integer] :length @option options [String] :value @option options [Class] :t {Int} subclass for :type
attribute.
Default: {Int8}.
@option options [Class] :l {Int} subclass for :length
attribute.
Default: {Int8}.
@option options [Class] :v {String} subclass for :value
attribute.
Default: {Types::String}.
PacketGen::Types::Fields::new
# File lib/packetgen/types/tlv.rb, line 56 def initialize(options={}) Deprecation.deprecated_class(self.class, AbstractTLV) super self[:type] = options[:t].new(self.type) if options[:t] self[:length] = options[:l].new(self.length) if options[:l] self[:value] = options[:v].new if options[:v] self.type = options[:type] if options[:type] self.value = options[:value] if options[:value] self.length = options[:length] if options[:length] end
Public Instance Methods
Return human readable type, if TYPES is defined @return [String]
# File lib/packetgen/types/tlv.rb, line 121 def human_type if human_types? htype = self.class::TYPES[type] htype = type if htype.nil? htype.to_s else type.to_s end end
Populate object from a binary string @param [String] str @return [Fields] self
# File lib/packetgen/types/tlv.rb, line 70 def read(str) idx = 0 self[:type].read str[idx, self[:type].sz] idx += self[:type].sz self[:length].read str[idx, self[:length].sz] idx += self[:length].sz self[:value].read str[idx, self.length] self end
@return [String]
# File lib/packetgen/types/tlv.rb, line 132 def to_human name = self.class.to_s.gsub(/.*::/, '') @typestr ||= if human_types? types = self.class::TYPES.values "%-#{types.max_by(&:length).size}s" else '%s' end @lenstr ||= "%-#{(2**(self[:length].width * 8) - 1).to_s.size}u" "#{name} type:#{@typestr} length:#{@lenstr} value:#{value.inspect}" % [human_type, length] end
Set type @param [::String,Integer] val @return [Integer] @raise [TypeError] class does not define TYPES @raise [ArgumentError] unknown string type
# File lib/packetgen/types/tlv.rb, line 90 def type=(val) case val when Integer self.old_type = val else raise TypeError, 'need an Integer' unless human_types? new_val = self.class::TYPES.key(val.to_s) raise ArgumentError, "unknown #{val} type" if new_val.nil? self.old_type = new_val end end
Get value
@return [Object] depend on value
type
# File lib/packetgen/types/tlv.rb, line 115 def value self[:value].to_human end
Set value
. May set length
if value is a {Types::String}. @param [::String,Integer] val @return [::String,Integer]
# File lib/packetgen/types/tlv.rb, line 107 def value=(val) self[:value].from_human val self.length = self[:value].sz val end
Private Instance Methods
# File lib/packetgen/types/tlv.rb, line 147 def human_types? self.class.const_defined? :TYPES end