# -*- encoding: utf-8 -*- # -*- frozen_string_literal: true -*- # -*- warn_indent: true -*- require "unit_measurements/unit_groups/weight" module CompositeUnitMeasurements # A parser handling +weight+ measurements, particularly for composite units # like +pound-ounce+, +stone-pound+, +kilogramme-gramme+, etc. # # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 0.2.0 class Weight class << self # Parses a given +string+ into a +UnitMeasurements::Weight+ object. # # @param [String] string The string to parse for weight measurement. # @return [UnitMeasurements::Weight] # Returns a UnitMeasurements::Weight object if parsing is successful. # @raise [UnitMeasurements::ParseError] # If the string does not match any known format. # # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 0.2.0 def parse(string) case string when POUND_OUNCE then parse_pound_ounce(string) when STONE_POUND then parse_stone_pound(string) else raise UnitMeasurements::ParseError, string end end private # @private # Parses a +string+ representing a weight in the format of +pound-ounce+. # # @param [String] string # The string representing weight measurement in the format of *pound-ounce*. # @return [UnitMeasurements::Weight] # Returns a UnitMeasurements::Weight object if parsing is successful. # # @see POUND_OUNCE # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 0.2.0 def parse_pound_ounce(string) pound, ounce = string.match(POUND_OUNCE)&.captures if pound && ounce UnitMeasurements::Weight.new(pound, :lb) + UnitMeasurements::Weight.new(ounce, :oz) end end # @private # Parses a +string+ representing a weight in the format of +stone-pound+. # # @param [String] string # The string representing weight measurement in the format of *stone-pound*. # @return [UnitMeasurements::Weight] # Returns a UnitMeasurements::Weight object if parsing is successful. # # @see STONE_POUND # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 0.2.0 def parse_stone_pound(string) stone, pound = string.match(STONE_POUND)&.captures if stone && pound UnitMeasurements::Weight.new(stone, :st) + UnitMeasurements::Weight.new(pound, :lb) end end end private # Regex pattern for aliases of +pound+ unit. # # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 0.2.0 POUND_UNITS = /(?:#|lb|lbs|lbm|pound-mass|pound(?:s)?)/.freeze # Regex pattern for aliases of +ounce+ unit. # # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 0.2.0 OUNCE_UNITS = /(?:oz|ounce(?:s)?)/.freeze # Regex pattern for aliases of +stone+ unit. # # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 0.2.0 STONE_UNITS = /(?:st|stone(?:s)?)/.freeze # Regex pattern for parsing a weight measurement in the format of +pound-ounce+. # # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 0.2.0 POUND_OUNCE = /\A#{ANY_NUMBER}\s*#{POUND_UNITS}\s*#{ANY_NUMBER}\s*#{OUNCE_UNITS}\z/.freeze # Regex pattern for parsing a weight measurement in the format of +stone-pound+. # # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 0.2.0 STONE_POUND = /\A#{ANY_NUMBER}\s*#{STONE_UNITS}\s*#{ANY_NUMBER}\s*#{POUND_UNITS}\z/.freeze end end