summaryrefslogtreecommitdiffstats
path: root/include/ipmid/message
diff options
context:
space:
mode:
Diffstat (limited to 'include/ipmid/message')
-rw-r--r--include/ipmid/message/pack.hpp37
-rw-r--r--include/ipmid/message/unpack.hpp54
2 files changed, 65 insertions, 26 deletions
diff --git a/include/ipmid/message/pack.hpp b/include/ipmid/message/pack.hpp
index 18863c4..598e650 100644
--- a/include/ipmid/message/pack.hpp
+++ b/include/ipmid/message/pack.hpp
@@ -20,6 +20,7 @@
#include <memory>
#include <optional>
#include <phosphor-logging/log.hpp>
+#include <string_view>
#include <tuple>
#include <utility>
#include <variant>
@@ -239,6 +240,26 @@ struct PackSingle<std::vector<uint8_t>>
{
static int op(Payload& p, const std::vector<uint8_t>& t)
{
+ if (p.bitCount != 0)
+ {
+ return 1;
+ }
+ p.raw.reserve(p.raw.size() + t.size());
+ p.raw.insert(p.raw.end(), t.begin(), t.end());
+ return 0;
+ }
+};
+
+/** @brief Specialization of PackSingle for std::string_view */
+template <>
+struct PackSingle<std::string_view>
+{
+ static int op(Payload& p, const std::string_view& t)
+ {
+ if (p.bitCount != 0)
+ {
+ return 1;
+ }
p.raw.reserve(p.raw.size() + t.size());
p.raw.insert(p.raw.end(), t.begin(), t.end());
return 0;
@@ -259,6 +280,22 @@ struct PackSingle<std::variant<T...>>
}
};
+/** @brief Specialization of PackSingle for Payload */
+template <>
+struct PackSingle<Payload>
+{
+ static int op(Payload& p, const Payload& t)
+ {
+ if (p.bitCount != 0 || t.bitCount != 0)
+ {
+ return 1;
+ }
+ p.raw.reserve(p.raw.size() + t.raw.size());
+ p.raw.insert(p.raw.end(), t.raw.begin(), t.raw.end());
+ return 0;
+ }
+};
+
} // namespace details
} // namespace message
diff --git a/include/ipmid/message/unpack.hpp b/include/ipmid/message/unpack.hpp
index 94f80f1..d9ccba4 100644
--- a/include/ipmid/message/unpack.hpp
+++ b/include/ipmid/message/unpack.hpp
@@ -99,26 +99,29 @@ struct UnpackSingle
}
return 0;
}
- else
+ else if constexpr (utility::is_tuple<T>::value)
{
- if constexpr (utility::is_tuple<T>::value)
+ bool priorError = p.unpackError;
+ size_t priorIndex = p.rawIndex;
+ // more stuff to unroll if partial bytes are out
+ size_t priorBitCount = p.bitCount;
+ fixed_uint_t<details::bitStreamSize> priorBits = p.bitStream;
+ int ret = p.unpack(t);
+ if (ret != 0)
{
- bool priorError = p.unpackError;
- size_t priorIndex = p.rawIndex;
- // more stuff to unroll if partial bytes are out
- size_t priorBitCount = p.bitCount;
- fixed_uint_t<details::bitStreamSize> priorBits = p.bitStream;
- int ret = p.unpack(t);
- if (ret != 0)
- {
- t = T();
- p.rawIndex = priorIndex;
- p.bitStream = priorBits;
- p.bitCount = priorBitCount;
- p.unpackError = priorError;
- }
- return 0;
+ t = T();
+ p.rawIndex = priorIndex;
+ p.bitStream = priorBits;
+ p.bitCount = priorBitCount;
+ p.unpackError = priorError;
}
+ return ret;
+ }
+ else
+ {
+ static_assert(
+ utility::dependent_false<T>::value,
+ "Attempt to unpack a type that has no IPMI unpack operation");
}
}
};
@@ -289,18 +292,21 @@ struct UnpackSingle<std::vector<T>>
{
static int op(Payload& p, std::vector<T>& t)
{
- int ret = 0;
while (p.rawIndex < p.raw.size())
{
t.emplace_back();
- ret = UnpackSingle<T>::op(p, t.back());
- if (ret)
+ if (UnpackSingle<T>::op(p, t.back()))
{
t.pop_back();
break;
}
}
- return ret;
+ // unpacking a vector is always successful:
+ // either stuff was unpacked successfully (return 0)
+ // or stuff was not unpacked, but should still return
+ // success because an empty vector or a not-fully-unpacked
+ // payload is not a failure.
+ return 0;
}
};
@@ -324,13 +330,9 @@ struct UnpackSingle<Payload>
{
static int op(Payload& p, Payload& t)
{
+ t = p;
// mark that this payload is being included in the args
p.trailingOk = true;
- t = p;
- // reset the unpacking flags so it can be properly checked
- t.trailingOk = false;
- t.unpackCheck = true;
- t.unpackError = false;
return 0;
}
};
OpenPOWER on IntegriCloud