app/models/coupdoeil/popover/option/offset.rb
# frozen_string_literal: true module Coupdoeil class Popover class Option class Offset < Coupdoeil::Popover::Option INTEGER_PART_BITS = 8 FLOAT_PART_BITS = 10 CONFIG_PART_BITS = 2 self.bit_size = INTEGER_PART_BITS + FLOAT_PART_BITS + CONFIG_PART_BITS class << self def parse(value) float_value = value.to_f return 0 if float_value.zero? base = 0 base |= 1 if float_value.negative? base |= 2 if value.is_a?(String) && value.end_with?("rem") integer, decimals = float_value.abs.to_s.split(".") base |= (decimals.to_i << CONFIG_PART_BITS) base |= (integer.to_i << CONFIG_PART_BITS + FLOAT_PART_BITS) base end end def validate! return ensure_no_overflow if (value in Float | Integer) || value.to_s.match?(/^-?\d+(\.\d{1,3})?(px|rem)?$/) raise_invalid_option("Value should be a signed float or integer, followed or not by 'rem' or 'px'.") end private def ensure_no_overflow float_value = value.to_f integer, decimals = float_value.abs.to_s.split(".").map(&:to_i) return if integer.in?(0..255) && decimals.in?(0..999) raise_invalid_option("Number should be comprised between -255.999 and 255.999, \ with a maximum of 3 decimal digits.") end end end end end