lib/command_mapper/types/key_value.rb
require_relative 'type'
require_relative 'str'
module CommandMapper
module Types
#
# Represents a key-value type.
#
class KeyValue < Type
# The separator String between the key and value.
#
# @return [String]
#
# @api semipublic
attr_reader :separator
# The key's type.
#
# @return [Type]
#
# @api semipublic
attr_reader :key
# The value's type.
#
# @return [Type]
#
# @api semipublic
attr_reader :value
#
# Initializes the key-value value type.
#
# @param [String] separator
# The key-value separator.
#
# @param [Type, Hash] key
# The key's value type.
#
# @param [Type, Hash] value
# The value's value type.
#
def initialize(separator: '=', key: Str.new, value: Str.new)
@separator = separator
if key.nil?
raise(ArgumentError,"key: keyword cannot be nil")
end
if value.nil?
raise(ArgumentError,"value: keyword cannot be nil")
end
@key = Types::Type(key)
@value = Types::Type(value)
end
#
# Valides the given value.
#
# @param [Object] value
# The given value to validate.
#
# @return [true, (false, String)]
# Returns true if the value is valid, or `false` and a validation error
# message if the value is not compatible.
#
# @api semipublic
#
def validate(value)
case value
when Hash
if value.length < 1
return [false, "cannot be empty"]
end
if value.length > 1
return [false, "cannot contain multiple key:value pairs (#{value.inspect})"]
end
key, value = value.first
when Array
if value.length < 2
return [false, "must contain two elements (#{value.inspect})"]
end
if value.length > 2
return [false, "cannot contain more than two elements (#{value.inspect})"]
end
key, value = value
else
return [false, "must be a Hash or an Array (#{value.inspect})"]
end
valid, message = @key.validate(key)
unless valid
return [false, "key #{message}"]
end
valid, message = @value.validate(value)
unless valid
return [false, "value #{message}"]
end
return true
end
#
# Formats a value into a key-value pair.
#
# @param [Hash, Array, #to_s] value
# The given value to format.
#
# @return [String]
# The formatted key-value pair.
#
# @api semipublic
#
def format(value)
case value
when Hash, Array
case value
when Hash
key, value = value.first
when Array
key, value = value
end
"#{@key.format(key)}#{@separator}#{@value.format(value)}"
else
super(value)
end
end
end
end
end