vaguerent/lib/vagrant/util/numeric.rb
Chris Roberts fd4da92245 Check file size prior to upload and automatically adjust options
When uploading box file, check if the size is greater than
    5GB. If the size is larger and the direct to storage option
    is enabled, disable the option due to current 5GB restriction
    on direct uploads.
2021-03-23 15:11:32 -07:00

90 lines
2.9 KiB
Ruby

require "log4r"
module Vagrant
module Util
class Numeric
# Authors Note: This conversion has been borrowed from the ActiveSupport Numeric class
# Conversion helper constants
KILOBYTE = 1024
MEGABYTE = KILOBYTE * 1024
GIGABYTE = MEGABYTE * 1024
TERABYTE = GIGABYTE * 1024
PETABYTE = TERABYTE * 1024
EXABYTE = PETABYTE * 1024
BYTES_CONVERSION_MAP = {KB: KILOBYTE, MB: MEGABYTE, GB: GIGABYTE, TB: TERABYTE,
PB: PETABYTE, EB: EXABYTE}
# Regex borrowed from the vagrant-disksize config class
SHORTHAND_MATCH_REGEX = /^(?<number>[0-9]+)\s?(?<unit>KB|MB|GB|TB)?$/
class << self
LOGGER = Log4r::Logger.new("vagrant::util::numeric")
# A helper that converts a shortcut string to its bytes representation.
# The expected format of `str` is essentially: "<Number>XX"
# Where `XX` is shorthand for KB, MB, GB, TB, PB, or EB. For example, 50 megabytes:
#
# str = "50MB"
#
# @param [String] - str
# @return [Integer,nil] - bytes - returns nil if method fails to convert to bytes
def string_to_bytes(str)
bytes = nil
str = str.to_s.strip
matches = SHORTHAND_MATCH_REGEX.match(str)
if matches
number = matches[:number].to_i
unit = matches[:unit].to_sym
if BYTES_CONVERSION_MAP.key?(unit)
bytes = number * BYTES_CONVERSION_MAP[unit]
else
LOGGER.error("An invalid unit or format was given, string_to_bytes cannot convert #{str}")
end
end
bytes
end
# Convert bytes to a user friendly string representation
#
# @param [Numeric] bytes Number of bytes to represent
# @return [String] user friendly output
def bytes_to_string(bytes)
# We want to locate the size that will return the
# smallest whole value number
BYTES_CONVERSION_MAP.sort { |a, b|
b.last <=> a.last
}.each do |suffix, size|
val = bytes.to_f / size
next if val < 1
val = sprintf("%.2f", val)
val.slice!(-1, 1) while val.end_with?("0")
val.slice!(-1, 1) if val.end_with?(".")
return "#{val}#{suffix}"
end
"#{bytes} byte#{"s" if bytes > 1}"
end
# Rounds actual value to two decimal places
#
# @param [Integer] bytes
# @return [Integer] megabytes - bytes representation in megabytes
def bytes_to_megabytes(bytes)
(bytes / MEGABYTE.to_f).round(2)
end
# @private
# Reset the cached values for platform. This is not considered a public
# API and should only be used for testing.
def reset!
instance_variables.each(&method(:remove_instance_variable))
end
end
end
end
end