rsl  1.1.0
ROS Support Library
parameter_validators.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <rsl/algorithm.hpp>
4 #include <rsl/export.hpp>
5 #include <rsl/static_string.hpp>
6 #include <rsl/static_vector.hpp>
7 
8 #include <rcl_interfaces/msg/set_parameters_result.hpp>
9 #include <rclcpp/parameter.hpp>
10 #include <tl_expected/expected.hpp>
11 
12 #include <fmt/ranges.h>
13 
14 namespace rsl {
15 
21 namespace detail {
22 template <typename T, typename Fn>
23 [[nodiscard]] auto size_compare(rclcpp::Parameter const& parameter, size_t const size,
24  std::string const& predicate_description, Fn const& predicate)
25  -> tl::expected<void, std::string> {
26  static constexpr auto format_string = "Length of parameter '{}' is '{}' but must be {} '{}'";
27  switch (parameter.get_type()) {
28  case rclcpp::ParameterType::PARAMETER_STRING:
29  if (auto value = parameter.get_value<std::string>(); !predicate(value.size(), size))
30  return tl::unexpected(fmt::format(format_string, parameter.get_name(), value.size(),
31  predicate_description, size));
32  break;
33  default:
34  if (auto value = parameter.get_value<std::vector<T>>(); !predicate(value.size(), size))
35  return tl::unexpected(fmt::format(format_string, parameter.get_name(), value.size(),
36  predicate_description, size));
37  }
38  return {};
39 }
40 
41 template <typename T, typename Fn>
42 [[nodiscard]] auto compare(rclcpp::Parameter const& parameter, T const& value,
43  std::string const& predicate_description, Fn const& predicate)
44  -> tl::expected<void, std::string> {
45  if (auto const param_value = parameter.get_value<T>(); !predicate(param_value, value))
46  return tl::unexpected(fmt::format("Parameter '{}' with the value '{}' must be {} '{}'",
47  parameter.get_name(), param_value, predicate_description,
48  value));
49  return {};
50 }
51 } // namespace detail
62 template <typename T>
63 [[nodiscard]] auto unique(rclcpp::Parameter const& parameter) -> tl::expected<void, std::string> {
64  if (is_unique(parameter.get_value<std::vector<T>>())) return {};
65  return tl::unexpected(
66  fmt::format("Parameter '{}' must only contain unique values", parameter.get_name()));
67 }
68 
75 template <typename T>
76 [[nodiscard]] auto subset_of(rclcpp::Parameter const& parameter, std::vector<T> const& valid_values)
77  -> tl::expected<void, std::string> {
78  auto const& values = parameter.get_value<std::vector<T>>();
79  for (auto const& value : values)
80  if (!contains(valid_values, value))
81  return tl::unexpected(
82  fmt::format("Entry '{}' in parameter '{}' is not in the set '{{{}}}'", value,
83  parameter.get_name(), fmt::join(valid_values, ", ")));
84  return {};
85 }
86 
93 template <typename T>
94 [[nodiscard]] auto fixed_size(rclcpp::Parameter const& parameter, size_t const size) {
95  return detail::size_compare<T>(parameter, size, "equal to", std::equal_to<>());
96 }
97 
104 template <typename T>
105 [[nodiscard]] auto size_gt(rclcpp::Parameter const& parameter, size_t const size) {
106  return detail::size_compare<T>(parameter, size, "greater than", std::greater<>());
107 }
108 
115 template <typename T>
116 [[nodiscard]] auto size_lt(rclcpp::Parameter const& parameter, size_t const size) {
117  return detail::size_compare<T>(parameter, size, "less than", std::less<>());
118 }
119 
127 template <typename T>
128 [[nodiscard]] auto not_empty(rclcpp::Parameter const& parameter)
129  -> tl::expected<void, std::string> {
130  switch (parameter.get_type()) {
131  case rclcpp::ParameterType::PARAMETER_STRING:
132  if (auto param_value = parameter.get_value<std::string>(); param_value.empty())
133  return tl::unexpected(
134  fmt::format("Parameter '{}' cannot be empty", parameter.get_name()));
135  break;
136  default:
137  if (auto param_value = parameter.get_value<std::vector<T>>(); param_value.empty())
138  return tl::unexpected(
139  fmt::format("Parameter '{}' cannot be empty", parameter.get_name()));
140  }
141  return {};
142 }
143 
150 template <typename T>
151 [[nodiscard]] auto element_bounds(rclcpp::Parameter const& parameter, T const& lower,
152  T const& upper) -> tl::expected<void, std::string> {
153  auto const& param_value = parameter.get_value<std::vector<T>>();
154  for (auto val : param_value)
155  if (val < lower || val > upper)
156  return tl::unexpected(
157  fmt::format("Value '{}' in parameter '{}' must be within bounds '[{}, {}]'", val,
158  parameter.get_name(), lower, upper));
159  return {};
160 }
161 
168 template <typename T>
169 [[nodiscard]] auto lower_element_bounds(rclcpp::Parameter const& parameter, T const& lower)
170  -> tl::expected<void, std::string> {
171  auto const& param_value = parameter.get_value<std::vector<T>>();
172  for (auto val : param_value)
173  if (val < lower)
174  return tl::unexpected(
175  fmt::format("Value '{}' in parameter '{}' must be above lower bound of '{}'", val,
176  parameter.get_name(), lower));
177  return {};
178 }
179 
186 template <typename T>
187 [[nodiscard]] auto upper_element_bounds(rclcpp::Parameter const& parameter, T const& upper)
188  -> tl::expected<void, std::string> {
189  auto const& param_value = parameter.get_value<std::vector<T>>();
190  for (auto val : param_value)
191  if (val > upper)
192  return tl::unexpected(
193  fmt::format("Value '{}' in parameter '{}' must be below upper bound of '{}'", val,
194  parameter.get_name(), upper));
195  return {};
196 }
197 
204 template <typename T>
205 [[nodiscard]] auto bounds(rclcpp::Parameter const& parameter, T const& lower, T const& upper)
206  -> tl::expected<void, std::string> {
207  auto const& param_value = parameter.get_value<T>();
208  if (param_value < lower || param_value > upper)
209  return tl::unexpected(
210  fmt::format("Parameter '{}' with the value '{}' must be within bounds '[{}, {}]'",
211  parameter.get_name(), param_value, lower, upper));
212  return {};
213 }
214 
221 template <typename T>
222 [[deprecated("Replace with rsl::gt_eq"), nodiscard]] auto lower_bounds(
223  rclcpp::Parameter const& parameter, T const& value) {
224  return detail::compare(parameter, value, "above lower bound of", std::greater_equal<T>());
225 }
226 
233 template <typename T>
234 [[deprecated("Replace with rsl::lt_eq"), nodiscard]] auto upper_bounds(
235  rclcpp::Parameter const& parameter, T const& value) {
236  return detail::compare(parameter, value, "below upper bound of", std::less_equal<T>());
237 }
238 
245 template <typename T>
246 [[nodiscard]] auto lt(rclcpp::Parameter const& parameter, T const& value) {
247  return detail::compare(parameter, value, "less than", std::less<T>());
248 }
249 
256 template <typename T>
257 [[nodiscard]] auto gt(rclcpp::Parameter const& parameter, T const& value) {
258  return detail::compare(parameter, value, "greater than", std::greater<T>());
259 }
260 
267 template <typename T>
268 [[nodiscard]] auto lt_eq(rclcpp::Parameter const& parameter, T const& value) {
269  return detail::compare(parameter, value, "less than or equal to", std::less_equal<T>());
270 }
271 
278 template <typename T>
279 [[nodiscard]] auto gt_eq(rclcpp::Parameter const& parameter, T const& value) {
280  return detail::compare(parameter, value, "greater than or equal to", std::greater_equal<T>());
281 }
282 
289 template <typename T>
290 [[nodiscard]] auto one_of(rclcpp::Parameter const& parameter, std::vector<T> const& collection)
291  -> tl::expected<void, std::string> {
292  auto const& param_value = parameter.get_value<T>();
293  if (contains(collection, param_value)) return {};
294  return tl::unexpected(fmt::format(
295  "Parameter '{}' with the value '{}' is not in the set '{{{}}}'", parameter.get_name(),
296  param_value, fmt::format("{}", fmt::join(collection, ", "))));
297 }
298 
302 [[nodiscard]] RSL_EXPORT auto to_parameter_result_msg(tl::expected<void, std::string> const& result)
303  -> rcl_interfaces::msg::SetParametersResult;
304 
305 } // namespace rsl
auto contains(Collection const &collection, typename Collection::const_reference value)
Determine if a collection contains a value. Example usage:
Definition: algorithm.hpp:19
auto is_unique(Collection collection)
Determine if all elements in a collection are unique. Example usage:
Definition: algorithm.hpp:37
auto fixed_size(rclcpp::Parameter const &parameter, size_t const size)
Is the array size of parameter equal to passed in size?
Definition: parameter_validators.hpp:94
auto lower_element_bounds(rclcpp::Parameter const &parameter, T const &lower) -> tl::expected< void, std::string >
Are all elements of parameter greater than lower bound?
Definition: parameter_validators.hpp:169
auto bounds(rclcpp::Parameter const &parameter, T const &lower, T const &upper) -> tl::expected< void, std::string >
Is parameter within bounds (inclusive)?
Definition: parameter_validators.hpp:205
auto gt_eq(rclcpp::Parameter const &parameter, T const &value)
Is parameter greater than or equal to some value?
Definition: parameter_validators.hpp:279
auto subset_of(rclcpp::Parameter const &parameter, std::vector< T > const &valid_values) -> tl::expected< void, std::string >
Are the values in parameter a subset of the valid values?
Definition: parameter_validators.hpp:76
auto unique(rclcpp::Parameter const &parameter) -> tl::expected< void, std::string >
Is every element of rclcpp::Parameter unique?
Definition: parameter_validators.hpp:63
auto one_of(rclcpp::Parameter const &parameter, std::vector< T > const &collection) -> tl::expected< void, std::string >
Is the parameter value one of a set of values?
Definition: parameter_validators.hpp:290
auto size_lt(rclcpp::Parameter const &parameter, size_t const size)
Is the array size of parameter less than passed in size?
Definition: parameter_validators.hpp:116
auto upper_element_bounds(rclcpp::Parameter const &parameter, T const &upper) -> tl::expected< void, std::string >
Are all elements of parameter less than some upper bound?
Definition: parameter_validators.hpp:187
auto element_bounds(rclcpp::Parameter const &parameter, T const &lower, T const &upper) -> tl::expected< void, std::string >
Are all elements of parameter within the bounds (inclusive)?
Definition: parameter_validators.hpp:151
auto not_empty(rclcpp::Parameter const &parameter) -> tl::expected< void, std::string >
Is the size of the value passed in not zero?
Definition: parameter_validators.hpp:128
RSL_EXPORT auto to_parameter_result_msg(tl::expected< void, std::string > const &result) -> rcl_interfaces::msg::SetParametersResult
Convert the result of a validator function into a SetParametersResult msg.
auto lower_bounds(rclcpp::Parameter const &parameter, T const &value)
Is parameter within some lower bound (same as gt_eq)?
Definition: parameter_validators.hpp:222
auto lt(rclcpp::Parameter const &parameter, T const &value)
Is parameter less than some value?
Definition: parameter_validators.hpp:246
auto size_gt(rclcpp::Parameter const &parameter, size_t const size)
Is the array size of parameter greater than passed in size?
Definition: parameter_validators.hpp:105
auto gt(rclcpp::Parameter const &parameter, T const &value)
Is parameter greater than some value?
Definition: parameter_validators.hpp:257
auto lt_eq(rclcpp::Parameter const &parameter, T const &value)
Is parameter less than or equal to some value?
Definition: parameter_validators.hpp:268
auto upper_bounds(rclcpp::Parameter const &parameter, T const &value)
Is parameter within some upper bound (same as lt_eq)?
Definition: parameter_validators.hpp:234