- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
require "refinements/array"
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
            
              
            
            
# The gem namespace.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Versionaire
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module_function
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
            
              
            
            
  # Conversion function (strict) for casting an object into a version.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  def Version object
           
        
      
        
          
- 
            
              82
            
            
              
            
            
    Converter.new(object).then do |converter|
           
        
      
        
          
- 
            
              82
            
            
              
                
                  when: 56
                
              
            
            
      case object
           
        
      
        
          
- 
            
              56
            
            
              
                
                  when: 10
                
              
            
            
        when String then converter.from_string
           
        
      
        
          
- 
            
              10
            
            
              
                
                  when: 10
                
              
            
            
        when Array then converter.from_array
           
        
      
        
          
- 
            
              10
            
            
              
                
                  when: 2
                
              
            
            
        when Hash then converter.from_hash
           
        
      
        
          
- 
            
              2
            
            
              
                
                  else: 4
                
              
            
            
        when Version then object
           
        
      
        
          
- 
            
              4
            
            
              
            
            
        else converter.from_object
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
            
              
            
            
  # Aids with converting objects into valid versions.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  class Converter
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    using Refinements::Array
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def initialize object, model: Version
           
        
      
        
          
- 
            
              82
            
            
              
            
            
      @object = object
           
        
      
        
          
- 
            
              82
            
            
              
            
            
      @model = model
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def from_string
           
        
      
        
          
- 
            
              56
            
            
              
            
            
      body = "Use: <major>.<minor>.<patch>, <major>.<minor>, <major>, or empty string."
           
        
      
        
          
- 
            
              56
            
            
              
                
                  else: 53
                
              
                
                  then: 3
                
              
            
            
      fail Error, error_message(object, body) unless PATTERN.match? object
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              53
            
            
              
            
            
      string_to_version
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def from_array
           
        
      
        
          
- 
            
              10
            
            
              
            
            
      body = "Use: [<major>, <minor>, <patch>], [<major>, <minor>], [<major>], or []."
           
        
      
        
          
- 
            
              10
            
            
              
                
                  else: 8
                
              
                
                  then: 2
                
              
            
            
      fail Error, error_message(object, body) unless (0..3).cover? object.size
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              8
            
            
              
            
            
      model.new(**attributes_for(object.pad(0, 3)))
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def from_hash
           
        
      
        
          
- 
            
              10
            
            
              
            
            
      body = "Use: {major: <major>, minor: <minor>, patch: <patch>}, " \
           
        
      
        
          
- 
            
            
              
            
            
             "{major: <major>, minor: <minor>}, {major: <major>}, or {}."
           
        
      
        
          
- 
            
              10
            
            
              
                
                  else: 8
                
              
                
                  then: 2
                
              
            
            
      fail Error, error_message(object, body) unless required_keys?
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              8
            
            
              
            
            
      Version[**object]
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def from_object
           
        
      
        
          
- 
            
              4
            
            
              
            
            
      fail Error, error_message(object, "Use: String, Array, Hash, or Version.")
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    attr_reader :object, :model
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def string_to_version
           
        
      
        
          
- 
            
              53
            
            
              
            
            
      object.split(DELIMITER)
           
        
      
        
          
- 
            
            
              
            
            
            .map(&:to_i)
           
        
      
        
          
- 
            
              53
            
            
              
            
            
            .then { |numbers| numbers.pad 0, 3 }
           
        
      
        
          
- 
            
              53
            
            
              
            
            
            .then { |values| model.new(**attributes_for(values)) }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def attributes_for(values) = model.members.zip(values).to_h
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              15
            
            
              
            
            
    def required_keys? = object.keys.all? { |key| model.members.include? key }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def error_message(object, body) = "Invalid version conversion: #{object}. #{body}"
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  private_constant :Converter
           
        
      
        
          
- 
            
            
              
            
            
end