#!/usr/bin/env ruby -w # # ByteSize # # bytesize.rb # # © 2018 Adam Hunt # Created: 2018-01-17 # Modified: 2018-04-09 # ## # :title: ByteSize Documentation # # :include: ../README.md # require 'bytesize/version' require 'pathname' # This class is used to represent a size in bytes. # # It uses the {SI}[https://en.wikipedia.org/wiki/International_System_of_Units] standard unit symbols: kB, MB, GB, TB, PB, EB, ZB, YB. # # For a version that uses the {IEC}[https://en.wikipedia.org/wiki/ISO/IEC_80000] standard unit symbols, see {IECByteSize}[IECByteSize.html]. # # === Examples of use # # ByteSize.new( 4127 ) #=> (4.13 kB) # ByteSize.new( "22 GB" ) #=> (22 GB) # ByteSize.new( "22 GiB" ) #=> (23.62 GB) # # ByteSize.bytes( 42 ) #=> (42 bytes) # # ByteSize.kb( 42 ) #=> (42 kB) # ByteSize.mb( 42 ) #=> (42 MB) # ByteSize.gb( 42 ) #=> (42 GB) # ByteSize.tb( 42 ) #=> (42 TB) # ByteSize.pb( 42 ) #=> (42 PB) # ByteSize.eb( 42 ) #=> (42 EB) # ByteSize.zb( 42 ) #=> (42 ZB) # ByteSize.yb( 42 ) #=> (42 YB) # # === Conversion of values: # # ByteSize.gb( 100 ).to_gib #=> 93.13225746154785 # # ByteSize.gib( 2.42 ).to_mib #=> 2478.079999923706 # # === With numeric convenience methods: # # require 'bytesize/unit' # # 100.gb.to_gib #=> 93.13225746154785 # # 2.42.gib.to_mib #=> 2478.079999923706 # class ByteSize include Comparable # :stopdoc: SI_BASE = 1000 SI_ORDERS_OF_MAGNITUDE = { kB: SI_BASE, MB: SI_BASE**2, GB: SI_BASE**3, TB: SI_BASE**4, PB: SI_BASE**5, EB: SI_BASE**6, ZB: SI_BASE**7, YB: SI_BASE**8 } SI_UNIT_SYMBOLS = SI_ORDERS_OF_MAGNITUDE.keys.freeze IEC_BASE = 1024 IEC_ORDERS_OF_MAGNITUDE = { KiB: IEC_BASE, MiB: IEC_BASE**2, GiB: IEC_BASE**3, TiB: IEC_BASE**4, PiB: IEC_BASE**5, EiB: IEC_BASE**6, ZiB: IEC_BASE**7, YiB: IEC_BASE**8 } IEC_UNIT_SYMBOLS = IEC_ORDERS_OF_MAGNITUDE.keys.freeze ALL_ORDERS_OF_MAGNITUDE = SI_ORDERS_OF_MAGNITUDE.merge(IEC_ORDERS_OF_MAGNITUDE).freeze # Must be after ALL_ORDERS_OF_MAGNITUDE SI_ORDERS_OF_MAGNITUDE[:bytes] = 1 SI_ORDERS_OF_MAGNITUDE.freeze IEC_ORDERS_OF_MAGNITUDE[:bytes] = 1 IEC_ORDERS_OF_MAGNITUDE.freeze # :startdoc: ALL_UNIT_SYMBOLS = ALL_ORDERS_OF_MAGNITUDE.keys.freeze BASE = SI_BASE UNIT_SYMBOLS = SI_UNIT_SYMBOLS ORDERS_OF_MAGNITUDE = SI_ORDERS_OF_MAGNITUDE # :stopdoc: # Creates convenience methods for all unit symbols ALL_ORDERS_OF_MAGNITUDE.each do |s,om| m = s.downcase define_singleton_method(m) do |val| raise( TypeError, "expected #{Numeric}, got #{val.class}" ) unless val.is_a?(Numeric) self.new(( val * om ).round) end define_method(:"to_#{m}") do bytes / Float(om) end end # :startdoc: # :stopdoc: BYTES_REGEX = /\A\s*(\-?[0-9]+)\s*(bytes)?\s*\z/.freeze SI_REGEX = /\A\s*(\-?[0-9]+(\.[0-9]+)?)\s*(#{ SI_UNIT_SYMBOLS.join('|') })\s*\z/i.freeze IEC_REGEX = /\A\s*(\-?[0-9]+(\.[0-9]+)?)\s*(#{ IEC_UNIT_SYMBOLS.join('|') })\s*\z/i.freeze # :startdoc: ## # :call-seq: # ByteSize.bytes( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n bytes. # def self.bytes( b ) raise( TypeError, "expected #{Numeric}, got #{b.class}" ) unless b.is_a?(Numeric) self.new( b.round ) end ## # :call-seq: # ByteSize.kb( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n kilobytes. # # :singleton-method: kb ## # :call-seq: # ByteSize.mb( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n megabytes. # # :singleton-method: mb ## # :call-seq: # ByteSize.gb( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n gigabytes. # # :singleton-method: gb ## # :call-seq: # ByteSize.tb( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n terabytes. # # :singleton-method: tb ## # :call-seq: # ByteSize.pb( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n petabytes. # # :singleton-method: pb ## # :call-seq: # ByteSize.eb( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n exabytes. # # :singleton-method: eb ## # :call-seq: # ByteSize.zb( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n zettabytes. # # :singleton-method: zb ## # :call-seq: # ByteSize.yb( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n yottabytes. # # :singleton-method: yb ## # :call-seq: # ByteSize.kib( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n kibibytes. # # :singleton-method: kib ## # :call-seq: # ByteSize.mib( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n mebibytes. # # :singleton-method: mib ## # :call-seq: # ByteSize.gib( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n gibibytes. # # :singleton-method: gib ## # :call-seq: # ByteSize.tib( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n tebibytes. # # :singleton-method: tib ## # :call-seq: # ByteSize.pib( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n pebibytes. # # :singleton-method: pib ## # :call-seq: # ByteSize.eib( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n exbibytes. # # :singleton-method: eib ## # :call-seq: # ByteSize.zib( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n zebibytes. # # :singleton-method: zib ## # :call-seq: # ByteSize.yib( n ) -> bytesize # # Returns a new instance of {ByteSize}[ByteSize.html] representing n yobibytes. # # :singleton-method: yib ## # call-seq: # ByteSize.parse( string ) -> bytesize # # Parses a {String}[https://ruby-doc.org/core/String.html] into either a # {ByteSize}[ByteSize.html] or {IECByteSize}[IECByteSize.html] depending on it's unit symbol. # def self.parse( val ) if val.is_a?(String) if m = val.match(BYTES_REGEX) ByteSize.new( m[1].to_i ) elsif m = val.match(SI_REGEX) ByteSize.send( m[3].downcase.to_sym, m[2].nil? ? m[1].to_i : m[1].to_f ) elsif m = val.match(IEC_REGEX) IECByteSize.send( m[3].downcase.to_sym, m[2].nil? ? m[1].to_i : m[1].to_f ) else raise( ArgumentError, "invalid #{ByteSize} or #{IECByteSize} string: #{val.inspect}" ) end else raise( TypeError, "expected #{String}, got #{val.class}" ) end end # :stopdoc: def self.new( val ) case val when ByteSize super( val.bytes ) when Integer super( val ) when String if m = val.match(BYTES_REGEX) super( m[1].to_i ) elsif m = val.match(SI_REGEX) self.send( m[3].downcase.to_sym, m[2].nil? ? m[1].to_i : m[1].to_f ) elsif m = val.match(IEC_REGEX) self.send( m[3].downcase.to_sym, m[2].nil? ? m[1].to_i : m[1].to_f ) else raise( ArgumentError, "invalid #{self} string: #{val.inspect}" ) end else raise( TypeError, "no implicit conversion of #{val.class} into #{self}" ) end end # :startdoc: ## # call-seq: # new( integer ) # new( string ) # # Create a new instance of {ByteSize}[ByteSize.html] from an {Integer}[https://ruby-doc.org/core/Integer.html] # or {String}[https://ruby-doc.org/core/String.html]. # def initialize( bytes ) @bytes = bytes end ## # :call-seq: # to_kb -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of kilobytes. # # :method: to_kb ## # :call-seq: # to_mb -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of megabytes. # # :method: to_mb ## # :call-seq: # to_gb -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of gigabytes. # # :method: to_gb ## # :call-seq: # to_tb -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of terabytes. # # :method: to_tb ## # :call-seq: # to_pb -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of petabytes. # # :method: to_pb ## # :call-seq: # to_eb -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of exabytes. # # :method: to_eb ## # :call-seq: # to_zb -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of zettabytes. # # :method: to_zb ## # :call-seq: # to_yb -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of yottabytes. # # :method: to_yb ## # :call-seq: # to_kib -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of kibibytes. # # :method: to_kib ## # :call-seq: # to_mib -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of mebibytes. # # :method: to_mib ## # :call-seq: # to_gib -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of gibibytes. # # :method: to_gib ## # :call-seq: # to_tib -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of tebibytes. # # :method: to_tib ## # :call-seq: # to_pib -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of pebibytes. # # :method: to_pib ## # :call-seq: # to_eib -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of exbibytes. # # :method: to_eib ## # :call-seq: # to_zib -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of zebibytes. # # :method: to_zib ## # :call-seq: # to_yib -> float # # Returns a {Float}[https://ruby-doc.org/core/Float.html] representing the equivalent number of yobibytes. # # :method: to_yib ## # :call-seq: # bytesize < val -> true or false # # Returns true if the value of bytesize is less than that of val. # def <( other ) case other when ByteSize bytes < other.bytes when Numeric bytes < other else raise( ArgumentError, "comparison of #{self.class} with #{other.inspect} failed" ) end end ## # :call-seq: # bytesize <= val -> true or false # # Returns true if the value of bytesize is less than or equal to that of val. # def <=( other ) case other when ByteSize bytes <= other.bytes when Numeric bytes <= other else raise( ArgumentError, "comparison of #{self.class} with #{other.inspect} failed" ) end end ## # :call-seq: # bytesize > val -> true or false # # Returns true if the value of bytesize is greater than that of val. # def >( other ) case other when ByteSize bytes > other.bytes when Numeric bytes > other else raise( ArgumentError, "comparison of #{self.class} with #{other.inspect} failed" ) end end ## # :call-seq: # bytesize >= val -> true or false # # Returns true if the value of bytesize is greater than or equal to that of val. # def >=( other ) case other when ByteSize bytes >= other.bytes when Numeric bytes >= other else raise( ArgumentError, "comparison of #{self.class} with #{other.inspect} failed" ) end end ## # :call-seq: # bytesize % val -> bytesize # # Performs a modulo operation with val, returning an instance of {ByteSize}[ByteSize.html]. # # val can be another {ByteSize}[ByteSize.html] or a {Numeric}[https://ruby-doc.org/core/Numeric.html]. # def %( val ) case val when Numeric self.class.new(( bytes % val ).round) when ByteSize self.class.new( bytes % val.bytes ) else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end ## # :call-seq: # bytesize * val -> bytesize # # Performs multiplication, returning an instance of {ByteSize}[ByteSize.html]. # # val must be a {Numeric}[https://ruby-doc.org/core/Numeric.html]. # Multiplication with another {ByteSize}[ByteSize.html] is disallowed because it does not make symantic sense. # def *( val ) case val when Numeric self.class.new(( bytes * val ).round) when ByteSize raise( TypeError, "cannot multiply #{ByteSize} with #{val.class}" ) else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end ## # :call-seq: # bytesize ** pow -> bytesize # # Raises bytesize to the power of pow, returning an instance of {ByteSize}[ByteSize.html]. # # pow must be a {Numeric}[https://ruby-doc.org/core/Numeric.html]. # Raising to the power of another {ByteSize}[ByteSize.html] is disallowed because it does not make symantic sense. # def **( pow ) case pow when Numeric self.class.new(( bytes ** pow ).round) when ByteSize raise( TypeError, "cannot raise #{ByteSize} to a power of #{pow.class}" ) else raise( TypeError, "#{pow.class} can't be coerced into #{self.class}" ) end end ## # :call-seq: # bytesize + val -> bytesize # # Performs addition, returning an instance of {ByteSize}[ByteSize.html]. # # val can be another {ByteSize}[ByteSize.html] or a {Numeric}[https://ruby-doc.org/core/Numeric.html]. # def +( val ) case val when Numeric self.class.new(( bytes + val ).round) when ByteSize self.class.new( bytes + val.bytes ) else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end ## # :call-seq: # +bytesize -> bytesize # # Unary Plus — Returns the receiver’s value. # def +@ self end ## # :call-seq: # bytesize - val -> bytesize # # Performs subtraction, returning an instance of {ByteSize}[ByteSize.html]. # # val can be another {ByteSize}[ByteSize.html] or a {Numeric}[https://ruby-doc.org/core/Numeric.html]. # def -( val ) case val when Numeric self.class.new(( bytes - val ).round) when ByteSize self.class.new( bytes - val.bytes ) else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end ## # :call-seq: # -bytesize -> bytesize # # Unary Minus — Returns the receiver’s value, negated. # def -@ self.class.new( 0 - bytes ) end ## # :call-seq: # bytesize / val -> bytesize or float # # Performs division. # # If val is a {Numeric}[https://ruby-doc.org/core/Numeric.html] # it returns an instance of {ByteSize}[ByteSize.html]. # If val is an instance of {ByteSize}[ByteSize.html] it returns # a {Float}[https://ruby-doc.org/core/Float.html]. # def /( val ) case val when Numeric self.class.new(( bytes / val ).round) when ByteSize bytes.to_f / val.bytes.to_f else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end ## # :call-seq: # bytesize <=> other -> -1, 0, 1, or nil # # Compares bytesize to other and returns 0 if they are equal, # -1 if bytesize is less than other, # or 1 if bytesize is greater than other. # # Returns nil if the two values are incomparable. # def <=>( other ) case other when Numeric bytes <=> other when ByteSize bytes <=> other.bytes else nil end end ## # :call-seq: # bytesize == other -> true or false # # Returns true if bytesize is equal to other. # # If other is not an instance of {ByteSize}[ByteSize.html] an attempt will be made to convert it to one. # def ==( other ) case other when Numeric bytes == other when ByteSize bytes == other.bytes else false end end ## # :call-seq: # bytesize === other -> true or false # # Alias for {==}[#method-i-3D-3D]. # # :method: === # :stopdoc: alias_method :===, :== # :startdoc: ## # :call-seq: # bytes -> integer # # Returns the number of bytes as an {Integer}[https://ruby-doc.org/core/Integer.html]. # # :method: bytes # :stopdoc: attr_accessor :bytes # :startdoc: # :stopdoc: def coerce( other ) if Numeric [ other, self.to_i ] else begin [ self.class.new(other), self ] rescue raise( TypeError, "#{other.class} can't be coerced into #{self.class}" ) end end end # :startdoc: ## # :call-seq: # eql?( other_bytesize ) -> true or false # # Returns true if the {ByteSize}[ByteSize.html] is equal to other_bytesize. # def eql?( other ) other.class == self.class && other.bytes == bytes end # :stopdoc: def hash bytes.hash end # :startdoc: ## # :call-seq: # inspect -> string # # Return a {String}[https://ruby-doc.org/core/String.html] describing this object. # # ====== Example: # # ByteSize.bytes(3000000000000) #=> (3 TB) # def inspect sprintf( '(%s)', to_s ) end ## # :call-seq: # negative? -> true or false # # Returns true if the {ByteSize}[ByteSize.html] is less than 0. # def negative? bytes < 0 end ## # :call-seq: # positive? -> true or false # # Returns true if the {ByteSize}[ByteSize.html] is greater than 0. # def positive? bytes > 0 end ## # :call-seq: # to_bytes -> integer # # Alias for #bytes. # # :method: to_bytes # :stopdoc: alias_method :to_bytes, :bytes # :startdoc: ## # :call-seq: # to_i -> integer # # Returns the number of bytes as an {Integer}[https://ruby-doc.org/core/Integer.html]. # def to_i bytes.to_i end ## # :call-seq: # to_iec -> iecbytesize # # Returns the size as an instance of {IECByteSize}[IECByteSize.html]. # # If called on an instance of {IECByteSize}[IECByteSize.html] it returns self. # def to_iec self.class == IECByteSize ? self : IECByteSize.new(self.to_i) end ## # :call-seq: # to_s -> string # to_s( decimal_places ) -> string # # Format this {ByteSize}[ByteSize.html] as a {String}[https://ruby-doc.org/core/String.html]. # # The second form formats it with exactly decimal_places decimal places. # # ====== Example: # # ByteSize.bytes(3000000000000).to_s #=> "3 TB" # ByteSize.bytes(2460000000000).to_s #=> "2.46 TB" # # ByteSize.bytes(3000000000000).to_s(2) #=> "3.00 TB" # ByteSize.bytes(1234567890000).to_s(2) #=> "1.23 TB" # ByteSize.bytes(1234567890000).to_s(4) #=> "1.2346 TB" # def to_s( decimal_places=nil ) unless decimal_places.nil? raise( TypeError, "expected #{Integer}, got #{decimal_places.class}" ) unless decimal_places.is_a?(Integer) raise( RangeError, "decimal places cannot be negative" ) unless decimal_places >= 0 end b = bytes.abs scale = self.class::ORDERS_OF_MAGNITUDE.sort{|(ak,av),(bk,bv)| av <=> bv } if b == 0 unit = scale.first else unit = scale.find_index{|k,v| v > b } if unit.nil? unit = scale.last else unit = scale[unit-1] end end if decimal_places.nil? sprintf( negative? ? '-%g %s' : '%g %s', ((b/Float(unit.last))*100).round/100.0, unit.first.to_s ) else sprintf( negative? ? "-%.0#{decimal_places}f %s" : "%.0#{decimal_places}f %s", b / Float(unit.last), unit.first.to_s ) end end ## # :call-seq: # to_si -> bytesize # # Returns the size as an instance of {ByteSize}[ByteSize.html]. # # If called on an instance of {ByteSize}[ByteSize.html] it returns self. # def to_si self.class == ByteSize ? self : ByteSize.new(self.to_i) end ## # :call-seq: # zero? -> true or false # # Returns true if the {ByteSize}[ByteSize.html] has a zero value. # def zero? bytes == 0 end end # This class is identical to {ByteSize}[ByteSize.html] except that all formatted output uses # the {IEC}[https://en.wikipedia.org/wiki/ISO/IEC_80000] standard unit symbols: # KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB. # # === Examples of use: # # IECByteSize.new( 4127 ) #=> (4.03 KiB) # IECByteSize.new( "22 GB" ) #=> (20.49 GiB) # IECByteSize.new( "22 GiB" ) #=> (22 GiB) # # IECByteSize.bytes( 42 ) #=> (42 bytes) # # IECByteSize.kib( 42 ) #=> (42 KiB) # IECByteSize.mib( 42 ) #=> (42 MiB) # IECByteSize.gib( 42 ) #=> (42 GiB) # IECByteSize.tib( 42 ) #=> (42 TiB) # IECByteSize.pib( 42 ) #=> (42 PiB) # IECByteSize.eib( 42 ) #=> (42 EiB) # IECByteSize.zib( 42 ) #=> (42 ZiB) # IECByteSize.yib( 42 ) #=> (42 YiB) # class IECByteSize < ByteSize # :stopdoc: BASE = IEC_BASE UNIT_SYMBOLS = IEC_UNIT_SYMBOLS ORDERS_OF_MAGNITUDE = IEC_ORDERS_OF_MAGNITUDE # :startdoc: end # {ByteSize}[ByteSize.html] adds three new methods to the {File}[http://ruby-doc.org/core/File.html] class: # # * ::bytesize # * ::bytesize? # * #bytesize # # Plus the equivalent methods for {IECByteSize}[IECByteSize.html]: # # * ::iecbytesize # * ::iecbytesize? # * #iecbytesize # class File ## # :call-seq: # File.bytesize( file_name ) -> bytesize # # Identical to {File.size}[http://ruby-doc.org/core/File.html#method-c-size] # except that the value is returned as an instance of {ByteSize}[ByteSize.html]. # def self.bytesize( file_name ) ByteSize.new( self.size(file_name) ) end ## # :call-seq: # File.bytesize?( file_name ) -> bytesize or nil # # Identical to {File.size?}[http://ruby-doc.org/core/File.html#method-c-size-3F] # except that the value is returned as an instance of {ByteSize}[ByteSize.html]. # def self.bytesize?( file_name ) sz = self.size?(file_name) sz.nil? ? nil : ByteSize.new(sz) end ## # :call-seq: # bytesize -> bytesize # # Identical to {File#size}[http://ruby-doc.org/core/File.html#method-i-size] # except that the value is returned as an instance of {ByteSize}[ByteSize.html]. # def bytesize ByteSize.new(size) end ## # :call-seq: # File.iecbytesize( file_name ) -> bytesize # # Identical to {File.size}[http://ruby-doc.org/core/File.html#method-c-size] # except that the value is returned as an instance of {IECByteSize}[IECByteSize.html]. # def self.iecbytesize( file_name ) IECByteSize.new( self.size(file_name) ) end ## # :call-seq: # File.iecbytesize?( file_name ) -> bytesize or nil # # Identical to {File.size?}[http://ruby-doc.org/core/File.html#method-c-size-3F] # except that the value is returned as an instance of {IECByteSize}[IECByteSize.html]. # def self.iecbytesize?( file_name ) sz = self.size?(file_name) sz.nil? ? nil : IECByteSize.new(sz) end ## # :call-seq: # iecbytesize -> bytesize # # Identical to {File#size}[http://ruby-doc.org/core/File.html#method-i-size] # except that the value is returned as an instance of {IECByteSize}[IECByteSize.html]. # def iecbytesize IECByteSize.new(size) end end # ByteSize adds two new methods to the {Pathname}[https://ruby-doc.org/stdlib/libdoc/pathname/rdoc/Pathname.html] class: # # * #bytesize # * #bytesize? # # Plus the equivalent methods for {IECByteSize}[IECByteSize.html]: # # * #iecbytesize # * #iecbytesize? # class Pathname ## # :call-seq: # bytesize -> bytesize # # Identical to {Pathname#size}[https://ruby-doc.org/stdlib/libdoc/pathname/rdoc/Pathname.html#method-i-size] # except that the value is returned as an instance of {ByteSize}[ByteSize.html]. # def bytesize ByteSize.new(size) end ## # :call-seq: # bytesize? -> bytesize or nil # # Identical to {Pathname#size?}[https://ruby-doc.org/stdlib/libdoc/pathname/rdoc/Pathname.html#method-i-size-3F] # except that the value is returned as an instance of {ByteSize}[ByteSize.html]. # def bytesize? sz = size? sz.nil? ? nil : ByteSize.new(sz) end ## # :call-seq: # iecbytesize -> bytesize # # Identical to {Pathname#size}[https://ruby-doc.org/stdlib/libdoc/pathname/rdoc/Pathname.html#method-i-size] # except that the value is returned as an instance of {IECByteSize}[IECByteSize.html]. # def iecbytesize IECByteSize.new(size) end ## # :call-seq: # iecbytesize? -> bytesize or nil # # Identical to {Pathname#size?}[https://ruby-doc.org/stdlib/libdoc/pathname/rdoc/Pathname.html#method-i-size-3F] # except that the value is returned as an instance of {IECByteSize}[IECByteSize.html]. # def iecbytesize? sz = size? sz.nil? ? nil : IECByteSize.new(sz) end end