93 lines
3.0 KiB
Ruby
93 lines
3.0 KiB
Ruby
# Copyright (c) HashiCorp, Inc.
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
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
|