mgmt: check enum range during decoding

This commit also makes use of prependStringBlock and readString
functions in encode/decode routines.

refs #3974

Change-Id: I86a4f16ea6f50fffeff72c8b416878740e65ef2a
diff --git a/src/encoding/block-helpers.hpp b/src/encoding/block-helpers.hpp
index f1e14ff..5634ed6 100644
--- a/src/encoding/block-helpers.hpp
+++ b/src/encoding/block-helpers.hpp
@@ -63,6 +63,39 @@
 uint64_t
 readNonNegativeInteger(const Block& block);
 
+/** @brief Read a non-negative integer from a TLV element and cast to the specified type
+ *  @tparam R result type, must be an integral type
+ *  @param block the TLV element
+ *  @throw tlv::Error block does not contain a valid non-negative integer or the number cannot be
+ *                    represented in R
+ */
+template<typename R>
+typename std::enable_if<std::is_integral<R>::value, R>::type
+readNonNegativeIntegerAs(const Block& block)
+{
+  uint64_t value = readNonNegativeInteger(block);
+  if (value > std::numeric_limits<R>::max()) {
+    BOOST_THROW_EXCEPTION(tlv::Error("Value in TLV element of type " + to_string(block.type()) +
+                          " is too large"));
+  }
+  return static_cast<R>(value);
+}
+
+/** @brief Read a non-negative integer from a TLV element and cast to the specified type
+ *  @tparam R result type, must be an enumeration type
+ *  @param block the TLV element
+ *  @throw tlv::Error block does not contain a valid non-negative integer or the number cannot be
+ *                    represented in R
+ *  @warning If R is an unscoped enum type, it must have a fixed underlying type. Otherwise, this
+ *           function may trigger unspecified behavior.
+ */
+template<typename R>
+typename std::enable_if<std::is_enum<R>::value, R>::type
+readNonNegativeIntegerAs(const Block& block)
+{
+  return static_cast<R>(readNonNegativeIntegerAs<typename std::underlying_type<R>::type>(block));
+}
+
 /** @brief Prepend an empty TLV element
  *  @param encoder an EncodingBuffer or EncodingEstimator
  *  @param type TLV-TYPE number
@@ -255,6 +288,7 @@
 
 using encoding::makeNonNegativeIntegerBlock;
 using encoding::readNonNegativeInteger;
+using encoding::readNonNegativeIntegerAs;
 using encoding::makeEmptyBlock;
 using encoding::makeStringBlock;
 using encoding::readString;