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

Returns a new function that produces a Hash

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

Public Instance Methods

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