class Puppet::Pops::Types::PHashType

@api public

Constants

DEFAULT
DEFAULT_KEY_PAIR_TUPLE
EMPTY
KEY_PAIR_TUPLE_SIZE

Attributes

key_type[RW]
value_type[RW]

Public Class Methods

array_as_hash(value) click to toggle source
     # File lib/puppet/pops/types/types.rb
2763 def self.array_as_hash(value)
2764   return value unless value.is_a?(Array)
2765   result = {}
2766   value.each_with_index {|v, idx| result[idx] = array_as_hash(v) }
2767   result
2768 end
new(key_type, value_type, size_type = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
2674 def initialize(key_type, value_type, size_type = nil)
2675   super(size_type)
2676   if !size_type.nil? && size_type.from == 0 && size_type.to == 0
2677     @key_type = PUnitType::DEFAULT
2678     @value_type = PUnitType::DEFAULT
2679   else
2680     @key_type = key_type.nil? ? PAnyType::DEFAULT : key_type
2681     @value_type = value_type.nil? ? PAnyType::DEFAULT : value_type
2682   end
2683 end
new_function(type) click to toggle source

Returns a new function that produces a Hash

     # File lib/puppet/pops/types/types.rb
2772 def self.new_function(type)
2773   @new_function ||= Puppet::Functions.create_loaded_function(:new_hash, type.loader) do
2774     local_types do
2775       type 'KeyValueArray = Array[Tuple[Any,Any],1]'
2776       type 'TreeArray = Array[Tuple[Array,Any],1]'
2777       type 'NewHashOption = Enum[tree, hash_tree]'
2778     end
2779 
2780     dispatch :from_tree do
2781       param           'TreeArray',       :from
2782       optional_param  'NewHashOption',   :build_option
2783     end
2784 
2785     dispatch :from_tuples do
2786       param           'KeyValueArray',  :from
2787     end
2788 
2789     dispatch :from_array do
2790       param           'Any',  :from
2791     end
2792 
2793     def from_tuples(tuple_array)
2794       Hash[tuple_array]
2795     end
2796 
2797     def from_tree(tuple_array, build_option = nil)
2798       if build_option.nil?
2799         return from_tuples(tuple_array)
2800       end
2801       # only remaining possible options is 'tree' or 'hash_tree'
2802 
2803       all_hashes = build_option == 'hash_tree'
2804       result = {}
2805       tuple_array.each do |entry|
2806         path = entry[0]
2807         value = entry[1]
2808         if path.empty?
2809           # root node (index [] was included - values merge into the result)
2810           # An array must be changed to a hash first as this is the root
2811           # (Cannot return an array from a Hash.new)
2812           if value.is_a?(Array)
2813             value.each_with_index {|v, idx| result[idx] = v }
2814           else
2815             result.merge!(value)
2816           end
2817         else
2818           r = path[0..-2].reduce(result) {|memo, idx| (memo.is_a?(Array) || memo.has_key?(idx)) ? memo[idx] : memo[idx] = {}}
2819           r[path[-1]]= (all_hashes ? PHashType.array_as_hash(value) : value)
2820         end
2821       end
2822       result
2823     end
2824 
2825     def from_array(from)
2826       case from
2827       when Array
2828         if from.size == 0
2829           {}
2830         else
2831           unless from.size % 2 == 0
2832             raise TypeConversionError.new(_('odd number of arguments for Hash'))
2833           end
2834           Hash[*from]
2835         end
2836       when Hash
2837         from
2838       else
2839         if PIterableType::DEFAULT.instance?(from)
2840           Hash[*Iterable.on(from).to_a]
2841         else
2842           t = TypeCalculator.singleton.infer(from).generalize
2843           raise TypeConversionError.new(_("Value of type %{type} cannot be converted to Hash") % { type: t })
2844         end
2845       end
2846     end
2847   end
2848 end
register_ptype(loader, ir) click to toggle source
     # File lib/puppet/pops/types/types.rb
2659 def self.register_ptype(loader, ir)
2660   create_ptype(loader, ir, 'CollectionType',
2661     'key_type' => {
2662       KEY_TYPE => POptionalType.new(PTypeType::DEFAULT),
2663       KEY_VALUE => PAnyType::DEFAULT
2664     },
2665     'value_type' => {
2666       KEY_TYPE => POptionalType.new(PTypeType::DEFAULT),
2667       KEY_VALUE => PAnyType::DEFAULT
2668     }
2669   )
2670 end

Public Instance Methods

accept(visitor, guard) click to toggle source
     # File lib/puppet/pops/types/types.rb
2685 def accept(visitor, guard)
2686   super
2687   @key_type.accept(visitor, guard)
2688   @value_type.accept(visitor, guard)
2689 end
element_type() click to toggle source
     # File lib/puppet/pops/types/types.rb
2691 def element_type
2692   if Puppet[:strict] != :off
2693     #TRANSLATOR 'Puppet::Pops::Types::PHashType#element_type' and '#value_type' are class and method names and should not be translated
2694     Puppet.warn_once('deprecations', 'Puppet::Pops::Types::PHashType#element_type',
2695       _('Puppet::Pops::Types::PHashType#element_type is deprecated, use #value_type instead'))
2696   end
2697   @value_type
2698 end
eql?(o) click to toggle source
     # File lib/puppet/pops/types/types.rb
2749 def eql?(o)
2750   super && @key_type == o.key_type && @value_type == o.value_type
2751 end
from_array(from) click to toggle source
     # File lib/puppet/pops/types/types.rb
2825 def from_array(from)
2826   case from
2827   when Array
2828     if from.size == 0
2829       {}
2830     else
2831       unless from.size % 2 == 0
2832         raise TypeConversionError.new(_('odd number of arguments for Hash'))
2833       end
2834       Hash[*from]
2835     end
2836   when Hash
2837     from
2838   else
2839     if PIterableType::DEFAULT.instance?(from)
2840       Hash[*Iterable.on(from).to_a]
2841     else
2842       t = TypeCalculator.singleton.infer(from).generalize
2843       raise TypeConversionError.new(_("Value of type %{type} cannot be converted to Hash") % { type: t })
2844     end
2845   end
2846 end
from_tree(tuple_array, build_option = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
2797 def from_tree(tuple_array, build_option = nil)
2798   if build_option.nil?
2799     return from_tuples(tuple_array)
2800   end
2801   # only remaining possible options is 'tree' or 'hash_tree'
2802 
2803   all_hashes = build_option == 'hash_tree'
2804   result = {}
2805   tuple_array.each do |entry|
2806     path = entry[0]
2807     value = entry[1]
2808     if path.empty?
2809       # root node (index [] was included - values merge into the result)
2810       # An array must be changed to a hash first as this is the root
2811       # (Cannot return an array from a Hash.new)
2812       if value.is_a?(Array)
2813         value.each_with_index {|v, idx| result[idx] = v }
2814       else
2815         result.merge!(value)
2816       end
2817     else
2818       r = path[0..-2].reduce(result) {|memo, idx| (memo.is_a?(Array) || memo.has_key?(idx)) ? memo[idx] : memo[idx] = {}}
2819       r[path[-1]]= (all_hashes ? PHashType.array_as_hash(value) : value)
2820     end
2821   end
2822   result
2823 end
from_tuples(tuple_array) click to toggle source
     # File lib/puppet/pops/types/types.rb
2793 def from_tuples(tuple_array)
2794   Hash[tuple_array]
2795 end
generalize() click to toggle source
     # File lib/puppet/pops/types/types.rb
2700 def generalize
2701   if self == DEFAULT || self == EMPTY
2702     self
2703   else
2704     key_t = @key_type
2705     key_t = key_t.generalize
2706     value_t = @value_type
2707     value_t = value_t.generalize
2708     @size_type.nil? && @key_type.equal?(key_t) && @value_type.equal?(value_t) ? self : PHashType.new(key_t, value_t, nil)
2709   end
2710 end
hash() click to toggle source
     # File lib/puppet/pops/types/types.rb
2722 def hash
2723   super ^ @key_type.hash ^ @value_type.hash
2724 end
instance?(o, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
2726 def instance?(o, guard = nil)
2727   # The inferred type of a class derived from Hash is either Runtime or Object. It's not assignable to the Hash type.
2728   return false unless o.instance_of?(Hash)
2729   if o.keys.all? {|key| @key_type.instance?(key, guard) } && o.values.all? {|value| @value_type.instance?(value, guard) }
2730     size_t = size_type
2731     size_t.nil? || size_t.instance?(o.size, guard)
2732   else
2733     false
2734   end
2735 end
is_the_empty_hash?() click to toggle source
     # File lib/puppet/pops/types/types.rb
2753 def is_the_empty_hash?
2754   self == EMPTY
2755 end
iterable?(guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
2737 def iterable?(guard = nil)
2738   true
2739 end
iterable_type(guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
2741 def iterable_type(guard = nil)
2742   if self == DEFAULT || self == EMPTY
2743     PIterableType.new(DEFAULT_KEY_PAIR_TUPLE)
2744   else
2745     PIterableType.new(PTupleType.new([@key_type, @value_type], KEY_PAIR_TUPLE_SIZE))
2746   end
2747 end
normalize(guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
2712 def normalize(guard = nil)
2713   if self == DEFAULT || self == EMPTY
2714     self
2715   else
2716     key_t = @key_type.normalize(guard)
2717     value_t = @value_type.normalize(guard)
2718     @size_type.nil? && @key_type.equal?(key_t) && @value_type.equal?(value_t) ? self : PHashType.new(key_t, value_t, @size_type)
2719   end
2720 end
resolve(loader) click to toggle source
     # File lib/puppet/pops/types/types.rb
2757 def resolve(loader)
2758   rkey_type = @key_type.resolve(loader)
2759   rvalue_type = @value_type.resolve(loader)
2760   rkey_type.equal?(@key_type) && rvalue_type.equal?(@value_type) ? self : self.class.new(rkey_type, rvalue_type, @size_type)
2761 end

Protected Instance Methods

_assignable?(o, guard) click to toggle source

Hash is assignable if o is a Hash and o's key and element types are assignable @api private

Calls superclass method Puppet::Pops::Types::PCollectionType#_assignable?
     # File lib/puppet/pops/types/types.rb
2859 def _assignable?(o, guard)
2860   case o
2861   when PHashType
2862     size_s = size_type
2863     return true if (size_s.nil? || size_s.from == 0) && o.is_the_empty_hash?
2864     return false unless @key_type.assignable?(o.key_type, guard) && @value_type.assignable?(o.value_type, guard)
2865     super
2866   when PStructType
2867     # hash must accept String as key type
2868     # hash must accept all value types
2869     # hash must accept the size of the struct
2870     o_elements = o.elements
2871     (size_type || DEFAULT_SIZE).instance?(o_elements.size, guard) &&
2872         o_elements.all? {|e| @key_type.instance?(e.name, guard) && @value_type.assignable?(e.value_type, guard) }
2873   else
2874     false
2875   end
2876 end