Class: Puppet::Pops::Types::PHashType

Inherits:
PCollectionType show all
Defined in:
lib/puppet/pops/types/types.rb

Constant Summary collapse

DEFAULT =
PHashType.new(nil, nil)
KEY_PAIR_TUPLE_SIZE =
PIntegerType.new(2, 2)
DEFAULT_KEY_PAIR_TUPLE =
PTupleType.new([PUnitType::DEFAULT, PUnitType::DEFAULT], KEY_PAIR_TUPLE_SIZE)
EMPTY =
PHashType.new(PUnitType::DEFAULT, PUnitType::DEFAULT, PIntegerType.new(0, 0))

Constants inherited from PCollectionType

Puppet::Pops::Types::PCollectionType::DEFAULT_SIZE, Puppet::Pops::Types::PCollectionType::NOT_EMPTY_SIZE, Puppet::Pops::Types::PCollectionType::ZERO_SIZE

Instance Attribute Summary collapse

Attributes inherited from PCollectionType

#size_type

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from PCollectionType

#has_empty_range?, #size_range

Methods inherited from PAnyType

#==, #assignable?, #callable?, #callable_args?, #callable_with?, #check_self_recursion, create, #create, #kind_of_callable?, #loader, #name, #new_function, #really_instance?, #roundtrip_with_string?, #simple_name, simple_name, #to_alias_expanded_s, #to_s

Methods inherited from TypedModelObject

_pcore_type, create_ptype, register_ptypes

Methods included from PuppetObject

#_pcore_all_contents, #_pcore_contents, #_pcore_init_hash, #_pcore_type, #to_s

Constructor Details

#initialize(key_type, value_type, size_type = nil) ⇒ PHashType

Returns a new instance of PHashType.



2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
# File 'lib/puppet/pops/types/types.rb', line 2684

def initialize(key_type, value_type, size_type = nil)
  super(size_type)
  if !size_type.nil? && size_type.from == 0 && size_type.to == 0
    @key_type = PUnitType::DEFAULT
    @value_type = PUnitType::DEFAULT
  else
    @key_type = key_type.nil? ? PAnyType::DEFAULT : key_type
    @value_type = value_type.nil? ? PAnyType::DEFAULT : value_type
  end
end

Instance Attribute Details

#key_typeObject



2682
2683
2684
# File 'lib/puppet/pops/types/types.rb', line 2682

def key_type
  @key_type
end

#value_typeObject



2682
2683
2684
# File 'lib/puppet/pops/types/types.rb', line 2682

def value_type
  @value_type
end

Class Method Details

.array_as_hash(value) ⇒ Object



2774
2775
2776
2777
2778
2779
2780
# File 'lib/puppet/pops/types/types.rb', line 2774

def self.array_as_hash(value)
  return value unless value.is_a?(Array)

  result = {}
  value.each_with_index { |v, idx| result[idx] = array_as_hash(v) }
  result
end

.new_function(type) ⇒ Object

Returns a new function that produces a Hash



2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
# File 'lib/puppet/pops/types/types.rb', line 2784

def self.new_function(type)
  @new_function ||= Puppet::Functions.create_loaded_function(:new_hash, type.loader) do
    local_types do
      type 'KeyValueArray = Array[Tuple[Any,Any],1]'
      type 'TreeArray = Array[Tuple[Array,Any],1]'
      type 'NewHashOption = Enum[tree, hash_tree]'
    end

    dispatch :from_tree do
      param           'TreeArray',       :from
      optional_param  'NewHashOption',   :build_option
    end

    dispatch :from_tuples do
      param           'KeyValueArray', :from
    end

    dispatch :from_array do
      param           'Any', :from
    end

    def from_tuples(tuple_array)
      tuple_array.to_h
    end

    def from_tree(tuple_array, build_option = nil)
      if build_option.nil?
        return from_tuples(tuple_array)
      end

      # only remaining possible options is 'tree' or 'hash_tree'

      all_hashes = build_option == 'hash_tree'
      result = {}
      tuple_array.each do |entry|
        path = entry[0]
        value = entry[1]
        if path.empty?
          # root node (index [] was included - values merge into the result)
          # An array must be changed to a hash first as this is the root
          # (Cannot return an array from a Hash.new)
          if value.is_a?(Array)
            value.each_with_index { |v, idx| result[idx] = v }
          else
            result.merge!(value)
          end
        else
          r = path[0..-2].reduce(result) { |memo, idx| (memo.is_a?(Array) || memo.has_key?(idx)) ? memo[idx] : memo[idx] = {} }
          r[path[-1]] = (all_hashes ? PHashType.array_as_hash(value) : value)
        end
      end
      result
    end

    def from_array(from)
      case from
      when Array
        if from.size == 0
          {}
        else
          unless from.size.even?
            raise TypeConversionError.new(_('odd number of arguments for Hash'))
          end

          Hash[*from]
        end
      when Hash
        from
      else
        if PIterableType::DEFAULT.instance?(from)
          Hash[*Iterable.on(from).to_a]
        else
          t = TypeCalculator.singleton.infer(from).generalize
          raise TypeConversionError.new(_("Value of type %{type} cannot be converted to Hash") % { type: t })
        end
      end
    end
  end
end

.register_ptype(loader, ir) ⇒ Object



2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
# File 'lib/puppet/pops/types/types.rb', line 2670

def self.register_ptype(loader, ir)
  create_ptype(loader, ir, 'CollectionType',
               'key_type' => {
                 KEY_TYPE => POptionalType.new(PTypeType::DEFAULT),
                 KEY_VALUE => PAnyType::DEFAULT
               },
               'value_type' => {
                 KEY_TYPE => POptionalType.new(PTypeType::DEFAULT),
                 KEY_VALUE => PAnyType::DEFAULT
               })
end

Instance Method Details

#accept(visitor, guard) ⇒ Object



2695
2696
2697
2698
2699
# File 'lib/puppet/pops/types/types.rb', line 2695

def accept(visitor, guard)
  super
  @key_type.accept(visitor, guard)
  @value_type.accept(visitor, guard)
end

#element_typeObject



2701
2702
2703
2704
2705
2706
2707
2708
# File 'lib/puppet/pops/types/types.rb', line 2701

def element_type
  if Puppet[:strict] != :off
    # TRANSLATOR 'Puppet::Pops::Types::PHashType#element_type' and '#value_type' are class and method names and should not be translated
    Puppet.warn_once('deprecations', 'Puppet::Pops::Types::PHashType#element_type',
                     _('Puppet::Pops::Types::PHashType#element_type is deprecated, use #value_type instead'))
  end
  @value_type
end

#eql?(o) ⇒ Boolean

Returns:

  • (Boolean)


2760
2761
2762
# File 'lib/puppet/pops/types/types.rb', line 2760

def eql?(o)
  super && @key_type == o.key_type && @value_type == o.value_type
end

#generalizeObject



2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
# File 'lib/puppet/pops/types/types.rb', line 2710

def generalize
  if self == DEFAULT || self == EMPTY
    self
  else
    key_t = @key_type
    key_t = key_t.generalize
    value_t = @value_type
    value_t = value_t.generalize
    @size_type.nil? && @key_type.equal?(key_t) && @value_type.equal?(value_t) ? self : PHashType.new(key_t, value_t, nil)
  end
end

#hashObject



2732
2733
2734
# File 'lib/puppet/pops/types/types.rb', line 2732

def hash
  super ^ @key_type.hash ^ @value_type.hash
end

#instance?(o, guard = nil) ⇒ Boolean

Returns:

  • (Boolean)


2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
# File 'lib/puppet/pops/types/types.rb', line 2736

def instance?(o, guard = nil)
  # The inferred type of a class derived from Hash is either Runtime or Object. It's not assignable to the Hash type.
  return false unless o.instance_of?(Hash)

  if o.keys.all? { |key| @key_type.instance?(key, guard) } && o.values.all? { |value| @value_type.instance?(value, guard) }
    size_t = size_type
    size_t.nil? || size_t.instance?(o.size, guard)
  else
    false
  end
end

#is_the_empty_hash?Boolean

Returns:

  • (Boolean)


2764
2765
2766
# File 'lib/puppet/pops/types/types.rb', line 2764

def is_the_empty_hash?
  self == EMPTY
end

#iterable?(guard = nil) ⇒ Boolean

Returns:

  • (Boolean)


2748
2749
2750
# File 'lib/puppet/pops/types/types.rb', line 2748

def iterable?(guard = nil)
  true
end

#iterable_type(guard = nil) ⇒ Object



2752
2753
2754
2755
2756
2757
2758
# File 'lib/puppet/pops/types/types.rb', line 2752

def iterable_type(guard = nil)
  if self == DEFAULT || self == EMPTY
    PIterableType.new(DEFAULT_KEY_PAIR_TUPLE)
  else
    PIterableType.new(PTupleType.new([@key_type, @value_type], KEY_PAIR_TUPLE_SIZE))
  end
end

#normalize(guard = nil) ⇒ Object



2722
2723
2724
2725
2726
2727
2728
2729
2730
# File 'lib/puppet/pops/types/types.rb', line 2722

def normalize(guard = nil)
  if self == DEFAULT || self == EMPTY
    self
  else
    key_t = @key_type.normalize(guard)
    value_t = @value_type.normalize(guard)
    @size_type.nil? && @key_type.equal?(key_t) && @value_type.equal?(value_t) ? self : PHashType.new(key_t, value_t, @size_type)
  end
end

#resolve(loader) ⇒ Object



2768
2769
2770
2771
2772
# File 'lib/puppet/pops/types/types.rb', line 2768

def resolve(loader)
  rkey_type = @key_type.resolve(loader)
  rvalue_type = @value_type.resolve(loader)
  rkey_type.equal?(@key_type) && rvalue_type.equal?(@value_type) ? self : self.class.new(rkey_type, rvalue_type, @size_type)
end