Module: MaxCube::Messages::Handler

Includes:
MaxCube::Messages
Included in:
Parser, Serializer, TCP::Handler, UDP::Handler
Defined in:
lib/maxcube/messages/handler.rb

Overview

This module provides methods that handles with messages regardless whether it is for parse or serialize purposes. It mostly contains methods that validates (returns Boolean) or checks (raises exception on failure) some part of message.

Constant Summary

PACK_FORMAT =

Format characters to String#unpack and Array#pack, for purposes to convert binary string to integer. Elements are sorted by integer size in bytes.

%w[x C n N N].freeze

Constants included from MaxCube::Messages

DAYS_OF_WEEK, DEVICE_MODE, DEVICE_TYPE

Instance Method Summary collapse

Methods included from MaxCube::Messages

#ary_elem, #ary_elem_id, #conv_args, #day_of_week, #day_of_week_id, #device_mode, #device_mode_id, #device_type, #device_type_id, #to_bool, #to_bools, #to_datetime, #to_datetimes, #to_float, #to_floats, #to_int, #to_ints

Instance Method Details

#check_data_type(raw_data) ⇒ String

Checks whether #valid_data_type is true. If not, exception is raised.

Returns:

  • (String)

    input raw data string.

Raises:

  • (TypeError)

    if argument is not valid.



31
32
33
34
# File 'lib/maxcube/messages/handler.rb', line 31

def check_data_type(raw_data)
  raise TypeError unless valid_data_type(raw_data)
  raw_data
end

#check_hash(hash) ⇒ Hash

As #valid_hash, but raises exception if hash is not valid. Calls #check_hash_msg_type, #check_hash_keys and #check_hash_values.

Parameters:

  • hash (Hash)

    input hash.

Returns:

  • (Hash)

    input hash.



175
176
177
178
179
180
# File 'lib/maxcube/messages/handler.rb', line 175

def check_hash(hash)
  check_hash_msg_type(hash)
  check_hash_keys(hash)
  check_hash_values(hash)
  hash
end

#check_hash_keys(hash) ⇒ Hash

As #valid_hash_keys, but raises exception if hash is not valid. Calls #maybe_check_valid_hash_keys.

Parameters:

  • hash (Hash)

    input hash.

Returns:

  • (Hash)

    input hash.



130
131
132
133
# File 'lib/maxcube/messages/handler.rb', line 130

def check_hash_keys(hash)
  maybe_check_valid_hash_keys(hash, true)
  hash
end

#check_hash_msg_type(hash) ⇒ Object

Checks whether message type character in hash is valid. Calls #check_msg_type. If argument is valid, it assigns the message type to internal variable.

Parameters:

  • hash (Hash)

    input hash.



98
99
100
# File 'lib/maxcube/messages/handler.rb', line 98

def check_hash_msg_type(hash)
  check_msg_type(hash[:type])
end

#check_hash_values(hash) ⇒ Hash

As #valid_hash_values, but raises exception if hash values are not valid.

Parameters:

  • hash (Hash)

    input hash.

Returns:

  • (Hash)

    input hash.

Raises:



149
150
151
152
153
154
155
# File 'lib/maxcube/messages/handler.rb', line 149

def check_hash_values(hash)
  return hash if valid_hash_values(hash)
  hash = hash.dup
  hash.delete(:type)
  raise InvalidMessageBody
    .new(@msg_type, "invalid hash values: #{hash}")
end

#check_msg(msg) ⇒ Object

As #valid_msg, but raises exception if message is invalid. Currently, it just calls #check_msg_msg_type.

Parameters:

  • msg (String)

    input message.



83
84
85
# File 'lib/maxcube/messages/handler.rb', line 83

def check_msg(msg)
  check_msg_msg_type(msg)
end

#check_msg_msg_type(msg) ⇒ Object

Checks whether message type character of message is valid. Calls #check_msg_type and #msg_msg_type (this method depends on conrete end-class). If argument is valid, it assigns the message type to internal variable.

Parameters:

  • msg (String)

    input message.



68
69
70
# File 'lib/maxcube/messages/handler.rb', line 68

def check_msg_msg_type(msg)
  check_msg_type(msg_msg_type(msg))
end

#check_msg_part_lengths(lengths, *args) ⇒ Array (private)

As #valid_msg_part_lengths, but raises exception on failure.

Returns:

  • (Array)

    args if lengths are satisfied.

Raises:



225
226
227
228
229
230
231
# File 'lib/maxcube/messages/handler.rb', line 225

def check_msg_part_lengths(lengths, *args)
  return args if valid_msg_part_lengths(lengths, *args)
  raise InvalidMessageBody
    .new(@msg_type,
         "invalid lengths of message parts #{args}" \
         " (lengths should be: #{lengths})")
end

#check_msg_type(msg_type) ⇒ String

Checks whether message type character is valid. Calls #maybe_check_valid_msg_type. If argument is valid, it assigns the message type to internal variable.

Parameters:

  • msg_type (String)

    input message type character.

Returns:

  • (String)

    message type character assigned to internal variable.

Raises:



50
51
52
53
# File 'lib/maxcube/messages/handler.rb', line 50

def check_msg_type(msg_type)
  maybe_check_valid_msg_type(msg_type, true)
  @msg_type
end

#decode(data) ⇒ String (private)

Decodes input data with only printable characters to binary data using Base64#decode64.

Parameters:

  • data (String)

    input Base64-encoded string.

Returns:

  • (String)

    raw data string.



283
284
285
# File 'lib/maxcube/messages/handler.rb', line 283

def decode(data)
  Base64.decode64(data)
end

#encode(data) ⇒ String (private)

Encodes input binary data to only printable characters using Base64#strict_encode64.

Parameters:

  • data (String)

    input raw data string.

Returns:

  • (String)

    Base64-encoded string.



275
276
277
# File 'lib/maxcube/messages/handler.rb', line 275

def encode(data)
  Base64.strict_encode64(data)
end

#maybe_check_valid_hash_keys(hash, check) ⇒ Boolean (private)

Helper method that is called by #valid_hash_keys or #check_hash_keys. It validates/checks whether given hash contain all mandatory keys (#msg_type_hash_keys) and not other than optional keys (#msg_type_hash_opt_keys).

Parameters:

  • hash (Hash)

    input hash.

  • check (Boolean)

    whether to check (raise exception on failure).

Returns:

  • (Boolean)

    true or false for valid/invalid hash keys if check is false.

Raises:



258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/maxcube/messages/handler.rb', line 258

def maybe_check_valid_hash_keys(hash, check)
  keys = msg_type_hash_keys(@msg_type).dup
  opt_keys = msg_type_hash_opt_keys(@msg_type)

  hash_keys = hash.keys - opt_keys - [:type]

  valid = hash_keys.sort == keys.sort
  return valid if !check || valid
  raise InvalidMessageBody
    .new(@msg_type, "invalid hash keys: #{hash_keys} " \
         "(should be: #{keys})")
end

#maybe_check_valid_msg_type(msg_type, check) ⇒ Object (private)

Helper method that is called by #valid_msg_type or #check_msg_type. It provides validation or check depending on input flag. If argument is valid, it assigns the message type to internal variable.

Parameters:

  • msg_type (String)

    input message type character.

  • check (Boolean)

    whether to check (raise exception on failure).

Raises:



196
197
198
199
200
201
202
# File 'lib/maxcube/messages/handler.rb', line 196

def maybe_check_valid_msg_type(msg_type, check)
  valid = msg_type&.length == 1 &&
          msg_types.include?(msg_type)
  return valid ? msg_type : false unless check
  @msg_type = msg_type
  raise InvalidMessageType.new(@msg_type) unless valid
end

#msg_type_hash_keys(msg_type) ⇒ Object

Returns hash keys that are related to given message type. Each hash with a message type should contain these keys. Calls #msg_type_which_hash_keys.

Parameters:

  • msg_type (String)

    message type that is being parsed/serialized.



106
107
108
# File 'lib/maxcube/messages/handler.rb', line 106

def msg_type_hash_keys(msg_type)
  msg_type_which_hash_keys(msg_type, false)
end

#msg_type_hash_opt_keys(msg_type) ⇒ Object

Returns optional hash keys that are related to given message type. Calls #msg_type_which_hash_keys.

Parameters:

  • msg_type (String)

    message type that is being parsed/serialized.



113
114
115
# File 'lib/maxcube/messages/handler.rb', line 113

def msg_type_hash_opt_keys(msg_type)
  msg_type_which_hash_keys(msg_type, true)
end

#msg_type_which_hash_keys(msg_type, optional = false) ⇒ Array<Symbol> (private)

Helper method that is called by #msg_type_hash_keys or #msg_type_hash_opt_keys. It accesses KEYS or OPT_KEYS (depending on input flag) from object's concrete end-class.

Parameters:

  • msg_type (String)

    message type that is being parsed/serialized.

  • optional (Boolean) (defaults to: false)

    whether to return optional or mandatory keys.

Returns:

  • (Array<Symbol>)

    mandatory or optional hash keys, depending on optional, related to message type. If constant is not found, empty array is returned.



242
243
244
245
# File 'lib/maxcube/messages/handler.rb', line 242

def msg_type_which_hash_keys(msg_type, optional = false)
  str = "Message#{msg_type.upcase}::" + (optional ? 'OPT_KEYS' : 'KEYS')
  self.class.const_defined?(str) ? self.class.const_get(str) : []
end

#msg_typesArray<String> (private)

Gets MSG_TYPES constant depending on object's end-class.

Returns:

  • (Array<String>)

    MSG_TYPES constant depending on object's end-class.



187
188
189
# File 'lib/maxcube/messages/handler.rb', line 187

def msg_types
  self.class.const_get('MSG_TYPES')
end

#valid_data_type(raw_data) ⇒ Boolean

Checks whether raw data string is String.

Parameters:

  • raw_data

    input raw data string.

Returns:

  • (Boolean)

    true if argument is String, false otherwise.



23
24
25
# File 'lib/maxcube/messages/handler.rb', line 23

def valid_data_type(raw_data)
  raw_data.is_a?(String)
end

#valid_hash(hash) ⇒ Boolean

Validates if given hash satisfies basic conditions for all hashes being used with messages. Calls #valid_hash_msg_type, #valid_hash_keys and #valid_hash_values.

Parameters:

  • hash (Hash)

    input hash.

Returns:

  • (Boolean)

    true if hash is valid (from general point of view).



164
165
166
167
168
# File 'lib/maxcube/messages/handler.rb', line 164

def valid_hash(hash)
  valid_hash_msg_type(hash) &&
    valid_hash_keys(hash) &&
    valid_hash_values(hash)
end

#valid_hash_keys(hash) ⇒ Object

Validates if given hash contain valid keys, depending on its message type (according to #msg_type_which_hash_keys). Calls #maybe_check_valid_hash_keys.

Parameters:

  • hash (Hash)

    input hash.



122
123
124
# File 'lib/maxcube/messages/handler.rb', line 122

def valid_hash_keys(hash)
  maybe_check_valid_hash_keys(hash, false)
end

#valid_hash_msg_type(hash) ⇒ Object

Validates whether message type character in hash is valid. Calls #valid_msg_type.

Parameters:

  • hash (Hash)

    input hash.



90
91
92
# File 'lib/maxcube/messages/handler.rb', line 90

def valid_hash_msg_type(hash)
  valid_msg_type(hash[:type])
end

#valid_hash_values(hash) ⇒ Boolean

Validates if values of given hash satisfies basic conditions for all hashes being used with messages.

Parameters:

  • hash (Hash)

    input hash.

Returns:

  • (Boolean)

    true if hash values are valid (from general point of view).



140
141
142
# File 'lib/maxcube/messages/handler.rb', line 140

def valid_hash_values(hash)
  hash.none? { |_, v| v.nil? }
end

#valid_msg(msg) ⇒ Object

Validates whether whole message is valid from general point of view, independently of parser/sserializer. Currently, it just calls #valid_msg_msg_type.

Parameters:

  • msg (String)

    input message.



76
77
78
# File 'lib/maxcube/messages/handler.rb', line 76

def valid_msg(msg)
  valid_msg_msg_type(msg)
end

#valid_msg_msg_type(msg) ⇒ Object

Validates whether message type character of message is valid. Calls #valid_msg_type and #msg_msg_type (this method depends on conrete end-class).

Parameters:

  • msg (String)

    input message.



59
60
61
# File 'lib/maxcube/messages/handler.rb', line 59

def valid_msg_msg_type(msg)
  valid_msg_type(msg_msg_type(msg))
end

#valid_msg_part_lengths(lengths, *args) ⇒ Boolean (private)

Checks whether given args satisfy lengths specified in input lengths. Missing positions in lengths means that no requirement is demanded at that index.

Parameters:

  • lengths (Array<Integer>)

    required lenghts of arguments.

  • args (Array<#length>)

    arguments to be validated.

Returns:

  • (Boolean)

    true if lengths of 'all' args fits to input lengths; false otherwise, or if any arg is nil, or if size of lengths is higher than number of args.



214
215
216
217
218
219
220
# File 'lib/maxcube/messages/handler.rb', line 214

def valid_msg_part_lengths(lengths, *args)
  return false if args.any?(&:nil?) ||
                  args.length < lengths.length
  args.each_with_index.all? do |v, i|
    !lengths[i] || v.length == lengths[i]
  end
end

#valid_msg_type(msg_type) ⇒ Boolean

Validates whether message type character is valid. Calls #maybe_check_valid_msg_type.

Parameters:

  • msg_type (String)

    input message type character.

Returns:

  • (Boolean)

    true if argument is valid message type.



40
41
42
# File 'lib/maxcube/messages/handler.rb', line 40

def valid_msg_type(msg_type)
  maybe_check_valid_msg_type(msg_type, false)
end