Update stdlib and concat to 6.1.0 both
[mirror/dsa-puppet.git] / 3rdparty / modules / stdlib / lib / puppet / parser / functions / validate_numeric.rb
1 #
2 # validate_numeric.rb
3 #
4 module Puppet::Parser::Functions
5   newfunction(:validate_numeric, :doc => <<-DOC
6     @summary
7       Validate that the first argument is a numeric value (or an array of numeric values). Abort catalog compilation if any of the checks fail.
8
9     The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
10     The third argument is optional and passes a minimum.  (All elements of) the first argument has to be greater or equal to this min.
11     If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
12     if (all elements of) the first argument are greater or equal to the given minimum.
13     It will fail if the first argument is not a numeric (Integer or Float) or array of numerics, and if arg 2 and arg 3 are not convertable to a numeric.
14
15     @return
16       Validate that the first argument is a numeric value (or an array of numeric values). Fail compilation if any of the checks fail.
17
18     For passing and failing usage, see `validate_integer()`. It is all the same for validate_numeric, yet now floating point values are allowed, too.
19
20     DOC
21              ) do |args|
22     function_deprecation([:validate_numeric, 'This method is deprecated, please use the stdlib validate_legacy function,
23                             with Stdlib::Compat::Numeric. There is further documentation for validate_legacy function in the README.'])
24
25     # tell the user we need at least one, and optionally up to two other parameters
26     raise Puppet::ParseError, "validate_numeric(): Wrong number of arguments; must be 1, 2 or 3, got #{args.length}" unless !args.empty? && args.length < 4
27
28     input, max, min = *args
29
30     # check maximum parameter
31     if args.length > 1
32       max = max.to_s
33       # allow max to be empty (or undefined) if we have a minimum set
34       if args.length > 2 && max == ''
35         max = nil
36       else
37         begin
38           max = Float(max)
39         rescue TypeError, ArgumentError
40           raise Puppet::ParseError, "validate_numeric(): Expected second argument to be unset or a Numeric, got #{max}:#{max.class}"
41         end
42       end
43     else
44       max = nil
45     end
46
47     # check minimum parameter
48     if args.length > 2
49       begin
50         min = Float(min.to_s)
51       rescue TypeError, ArgumentError
52         raise Puppet::ParseError, "validate_numeric(): Expected third argument to be unset or a Numeric, got #{min}:#{min.class}"
53       end
54     else
55       min = nil
56     end
57
58     # ensure that min < max
59     if min && max && min > max
60       raise Puppet::ParseError, "validate_numeric(): Expected second argument to be larger than third argument, got #{max} < #{min}"
61     end
62
63     # create lamba validator function
64     validator = ->(num) do
65       # check input < max
66       if max && num > max
67         raise Puppet::ParseError, "validate_numeric(): Expected #{input.inspect} to be smaller or equal to #{max}, got #{input.inspect}."
68       end
69       # check input > min (this will only be checked if no exception has been raised before)
70       if min && num < min
71         raise Puppet::ParseError, "validate_numeric(): Expected #{input.inspect} to be greater or equal to #{min}, got #{input.inspect}."
72       end
73     end
74
75     # if this is an array, handle it.
76     case input
77     when Array
78       # check every element of the array
79       input.each_with_index do |arg, pos|
80         begin
81           raise TypeError if arg.is_a?(Hash)
82           arg = Float(arg.to_s)
83           validator.call(arg)
84         rescue TypeError, ArgumentError
85           raise Puppet::ParseError, "validate_numeric(): Expected element at array position #{pos} to be a Numeric, got #{arg.class}"
86         end
87       end
88     # for the sake of compatibility with ruby 1.8, we need extra handling of hashes
89     when Hash
90       raise Puppet::ParseError, "validate_integer(): Expected first argument to be a Numeric or Array, got #{input.class}"
91     # check the input. this will also fail any stuff other than pure, shiny integers
92     else
93       begin
94         input = Float(input.to_s)
95         validator.call(input)
96       rescue TypeError, ArgumentError
97         raise Puppet::ParseError, "validate_numeric(): Expected first argument to be a Numeric or Array, got #{input.class}"
98       end
99     end
100   end
101 end