Suggest different variables to use if we want to tunnel both v4 and v6
[mirror/dsa-puppet.git] / 3rdparty / modules / stdlib / lib / puppet / parser / functions / values_at.rb
1 #
2 # values_at.rb
3 #
4 module Puppet::Parser::Functions
5   newfunction(:values_at, :type => :rvalue, :doc => <<-DOC
6     Finds value inside an array based on location.
7
8     The first argument is the array you want to analyze, and the second element can
9     be a combination of:
10
11     * A single numeric index
12     * A range in the form of 'start-stop' (eg. 4-9)
13     * An array combining the above
14
15     *Examples*:
16
17         values_at(['a','b','c'], 2)
18
19     Would return ['c'].
20
21         values_at(['a','b','c'], ["0-1"])
22
23     Would return ['a','b'].
24
25         values_at(['a','b','c','d','e'], [0, "2-3"])
26
27     Would return ['a','c','d'].
28
29     Note that since Puppet 4.0.0 it is possible to slice an array with index and count directly in the language.
30     A negative value is taken to be "from the end" of the array:
31
32         ['a', 'b', 'c', 'd'][1, 2]   # results in ['b', 'c']
33         ['a', 'b', 'c', 'd'][2, -1]  # results in ['c', 'd']
34         ['a', 'b', 'c', 'd'][1, -2]  # results in ['b', 'c']
35     DOC
36              ) do |arguments|
37
38     raise(Puppet::ParseError, "values_at(): Wrong number of arguments given (#{arguments.size} for 2)") if arguments.size < 2
39
40     array = arguments.shift
41
42     unless array.is_a?(Array)
43       raise(Puppet::ParseError, 'values_at(): Requires array to work with')
44     end
45
46     indices = [arguments.shift].flatten # Get them all ... Pokemon ...
47
48     if !indices || indices.empty?
49       raise(Puppet::ParseError, 'values_at(): You must provide at least one positive index to collect')
50     end
51
52     indices_list = []
53
54     indices.each do |i|
55       i = i.to_s
56       m = i.match(%r{^(\d+)(\.\.\.?|\-)(\d+)$})
57       if m
58         start = m[1].to_i
59         stop  = m[3].to_i
60
61         type = m[2]
62
63         raise(Puppet::ParseError, 'values_at(): Stop index in given indices range is smaller than the start index') if start > stop
64         raise(Puppet::ParseError, 'values_at(): Stop index in given indices range exceeds array size') if stop > array.size - 1 # First element is at index 0 is it not?
65
66         range = case type
67                 when %r{^(\.\.|\-)$} then (start..stop)
68                 when %r{^(\.\.\.)$}  then (start...stop) # Exclusive of last element ...
69                 end
70
71         range.each { |i| indices_list << i.to_i } # rubocop:disable Lint/ShadowingOuterLocalVariable : Value is meant to be shadowed
72       else
73         # Only positive numbers allowed in this case ...
74         unless i =~ %r{^\d+$}
75           raise(Puppet::ParseError, 'values_at(): Unknown format of given index')
76         end
77
78         # In Puppet numbers are often string-encoded ...
79         i = i.to_i
80
81         if i > array.size - 1 # Same story.  First element is at index 0 ...
82           raise(Puppet::ParseError, 'values_at(): Given index exceeds array size')
83         end
84
85         indices_list << i
86       end
87     end
88
89     # We remove nil values as they make no sense in Puppet DSL ...
90     result = indices_list.map { |i| array[i] }.compact
91
92     return result
93   end
94 end
95
96 # vim: set ts=2 sw=2 et :