Class: Nstrct::Argument

Inherits:
Object
  • Object
show all
Defined in:
lib/nstrct/argument.rb

Constant Summary collapse

DATATYPES =

Available datatypes and their argument code

{
  boolean: 1,
  int8: 10,
  int16: 11,
  int32: 12,
  int64: 13,
  uint8: 14,
  uint16: 15,
  uint32: 16,
  uint64: 17,
  float32: 21,
  float64: 22,
  string: 31,
  array: 32
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(datatype, value, array) ⇒ Argument

Instantiate a new Argument providing its datatype, value and arrayness



81
82
83
# File 'lib/nstrct/argument.rb', line 81

def initialize(datatype, value, array)
  @datatype, @value, @array = datatype.to_sym, value, array
end

Instance Attribute Details

#arrayObject (readonly)

Returns the value of attribute array.



78
79
80
# File 'lib/nstrct/argument.rb', line 78

def array
  @array
end

#datatypeObject (readonly)

Returns the value of attribute datatype.



78
79
80
# File 'lib/nstrct/argument.rb', line 78

def datatype
  @datatype
end

#valueObject (readonly)

Returns the value of attribute value.



78
79
80
# File 'lib/nstrct/argument.rb', line 78

def value
  @value
end

Class Method Details

.datatype_by_for_argument_code(code) ⇒ Object

Get the datatype of a argument code



23
24
25
# File 'lib/nstrct/argument.rb', line 23

def self.datatype_by_for_argument_code(code)
  DATATYPES.detect { |k, v| v == code }[0]
end

.parse(data) ⇒ Object

Parse a single argument from a buffer



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/nstrct/argument.rb', line 63

def self.parse(data)
  datatype = self.datatype_by_for_argument_code(data.slice!(0).unpack('C')[0])
  if datatype == :array
    array_datatype = self.datatype_by_for_argument_code(data.slice!(0).unpack('C')[0])
    array_num_elements = data.slice!(0).unpack('C')[0]
    values = []
    array_num_elements.times do
      values << self.parse_value(array_datatype, data)
    end
    return self.new(array_datatype, values, true)
  else
    return self.new(datatype, self.parse_value(datatype, data), false)
  end
end

.parse_value(datatype, data) ⇒ Object

Parse a single value of a buffer



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/nstrct/argument.rb', line 28

def self.parse_value(datatype, data)
  case datatype
  when :boolean
    return data.slice!(0).unpack('C')[0] == 1
  when :int8
    return data.slice!(0).unpack('c')[0]
  when :int16
    return data.slice!(0..1).unpack('s>')[0]
  when :int32
    return data.slice!(0..3).unpack('l>')[0]
  when :int64
    return data.slice!(0..7).unpack('q>')[0]
  when :uint8
    return data.slice!(0).unpack('C')[0]
  when :uint16
    return data.slice!(0..1).unpack('S>')[0]
  when :uint32
    return data.slice!(0..3).unpack('L>')[0]
  when :uint64
    return data.slice!(0..7).unpack('Q>')[0]
  when :float32
    return data.slice!(0..3).unpack('g')[0]
  when :float64
    return data.slice!(0..7).unpack('G')[0]
  when :string
    length = data.slice!(0).unpack('C')[0]
    return length > 0 ? data.slice!(0..length - 1) : ''
  when :array
    raise 'cannot parse array value directly'
  else
    raise "datatype '#{datatype}' not recognized"
  end
end

Instance Method Details

#inspectObject

Return comparable inspection



150
151
152
153
154
155
156
# File 'lib/nstrct/argument.rb', line 150

def inspect
  if @array
    "[#{@datatype.inspect}]=#{@value}"
  else
    "#{@datatype.inspect}=#{@value}"
  end
end

#packObject

Pack a single argument in a buffer



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/nstrct/argument.rb', line 129

def pack
  data = ''
  if @array
    data += [DATATYPES[:array]].pack('C')
    data += [DATATYPES[@datatype]].pack('C')
    if @value.is_a?(Array)
      data += [@value.size].pack('C')
      @value.each do |val|
        data = pack_value(@datatype, val, data)
      end
    else
      data += [0].pack('C')
    end
  else
    data += [DATATYPES[datatype]].pack('C')
    data = pack_value(@datatype, @value, data)
  end
  data
end

#pack_value(datatype, value, data) ⇒ Object

Pack a single value in a buffer



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/nstrct/argument.rb', line 86

def pack_value(datatype, value, data)
  case datatype
  when :boolean
    data += [to_boolean(value) ? 1 : 0].pack('C')
  when :int8
    data += [value.to_i].pack('c')
  when :int16
    data += [value.to_i].pack('s>')
  when :int32
    data += [value.to_i].pack('l>')
  when :int64
    data += [value.to_i].pack('q>')
  when :uint8
    data += [value.to_i].pack('C')
  when :uint16
    data += [value.to_i].pack('S>')
  when :uint32
    data += [value.to_i].pack('L>')
  when :uint64
    data += [value.to_i].pack('Q>')
  when :float32
    data += [value.to_f].pack('g')
  when :float64
    data += [value.to_f].pack('G')
  when :string
    data += [value.to_s.size].pack('C')
    data += value.to_s
  when :array
    raise 'cannot pack array value directly'
  else
    raise "datatype '#{datatype}' not recognized"
  end
  data
end

#to_boolean(value) ⇒ Object



121
122
123
124
125
126
# File 'lib/nstrct/argument.rb', line 121

def to_boolean(value)
  return value if value.is_a?(TrueClass) || value.is_a?(FalseClass)
  return Integer(value) >= 1
rescue
  return value == 'true'
end