gitlab-org--gitlab-foss/lib/gitlab/redis/boolean.rb

110 lines
2.9 KiB
Ruby

# frozen_string_literal: true
# A serializer for boolean values being stored in Redis.
#
# This is to ensure that booleans are stored in a consistent and
# testable way when being stored as strings in Redis.
#
# Examples:
#
# bool = Gitlab::Redis::Boolean.new(true)
# bool.to_s == "_b:1"
#
# Gitlab::Redis::Boolean.encode(true)
# => "_b:1"
#
# Gitlab::Redis::Boolean.decode("_b:1")
# => true
#
# Gitlab::Redis::Boolean.true?("_b:1")
# => true
#
# Gitlab::Redis::Boolean.true?("_b:0")
# => false
module Gitlab
module Redis
class Boolean
LABEL = "_b"
DELIMITER = ":"
TRUE_STR = "1"
FALSE_STR = "0"
BooleanError = Class.new(StandardError)
NotABooleanError = Class.new(BooleanError)
NotAnEncodedBooleanStringError = Class.new(BooleanError)
def initialize(value)
@value = value
end
# @return [String] the encoded boolean
def to_s
self.class.encode(@value)
end
class << self
# Turn a boolean into a string for storage in Redis
#
# @param value [Boolean] true or false
# @return [String] the encoded boolean
# @raise [NotABooleanError] if the value isn't true or false
def encode(value)
raise NotABooleanError, value unless bool?(value)
[LABEL, to_string(value)].join(DELIMITER)
end
# Decode a boolean string
#
# @param value [String] the stored boolean string
# @return [Boolean] true or false
# @raise [NotAnEncodedBooleanStringError] if the provided value isn't an encoded boolean
def decode(value)
raise NotAnEncodedBooleanStringError, value.class unless value.is_a?(String)
label, bool_str = *value.split(DELIMITER, 2)
raise NotAnEncodedBooleanStringError, label unless label == LABEL
from_string(bool_str)
end
# Decode a boolean string, then test if it's true
#
# @param value [String] the stored boolean string
# @return [Boolean] is the value true?
# @raise [NotAnEncodedBooleanStringError] if the provided value isn't an encoded boolean
def true?(encoded_value)
decode(encoded_value)
end
# Decode a boolean string, then test if it's false
#
# @param value [String] the stored boolean string
# @return [Boolean] is the value false?
# @raise [NotAnEncodedBooleanStringError] if the provided value isn't an encoded boolean
def false?(encoded_value)
!true?(encoded_value)
end
private
def bool?(value)
[true, false].include?(value)
end
def to_string(bool)
bool ? TRUE_STR : FALSE_STR
end
def from_string(str)
raise NotAnEncodedBooleanStringError, str unless [TRUE_STR, FALSE_STR].include?(str)
str == TRUE_STR
end
end
end
end
end