mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1596562: Add ParamTraits specializations for mozilla::Vector and std::vector; r=froydnj,bwc
While the need for adding `mozilla::Vector` is self-evident, we also need `std::vector` so that we can send some pre-existing telemetry data structures that use it. The new implementations are basically modified from the `nsTArray` specializations. Note that the `mozilla::Vector` specialization does support any type of allocator, so we still check for OOM failures in that case. This patch also removes the specialization for `std::vector` that lives in WebRTC in favour of the centralized implementation. Differential Revision: https://phabricator.services.mozilla.com/D53085 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
976b5d7d73
commit
abf8d763be
@ -20,36 +20,6 @@ typedef std::vector<std::string> StringVector;
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <typename T>
|
||||
struct ParamTraits<std::vector<T>> {
|
||||
typedef std::vector<T> paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aMsg->WriteUInt32(aParam.size());
|
||||
for (const T& elem : aParam) {
|
||||
WriteParam(aMsg, elem);
|
||||
}
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint32_t size;
|
||||
if (!aMsg->ReadUInt32(aIter, &size)) {
|
||||
return false;
|
||||
}
|
||||
while (size--) {
|
||||
// Only works when T is movable. Meh.
|
||||
T elem;
|
||||
if (!ReadParam(aMsg, aIter, &elem)) {
|
||||
return false;
|
||||
}
|
||||
aResult->emplace_back(std::move(elem));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::dom::OwningStringOrStringSequence> {
|
||||
typedef mozilla::dom::OwningStringOrStringSequence paramType;
|
||||
|
@ -24,11 +24,14 @@
|
||||
#endif
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsID.h"
|
||||
@ -638,6 +641,162 @@ struct ParamTraits<AutoTArray<E, N>> : ParamTraits<nsTArray<E>> {
|
||||
typedef AutoTArray<E, N> paramType;
|
||||
};
|
||||
|
||||
template <typename E, size_t N, typename AP>
|
||||
struct ParamTraits<mozilla::Vector<E, N, AP>> {
|
||||
typedef mozilla::Vector<E, N, AP> paramType;
|
||||
|
||||
// We write arrays of integer or floating-point data using a single pickling
|
||||
// call, rather than writing each element individually. We deliberately do
|
||||
// not use mozilla::IsPod here because it is perfectly reasonable to have
|
||||
// a data structure T for which IsPod<T>::value is true, yet also have a
|
||||
// ParamTraits<T> specialization.
|
||||
static const bool sUseWriteBytes =
|
||||
(mozilla::IsIntegral<E>::value || mozilla::IsFloatingPoint<E>::value);
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
uint32_t length = aParam.length();
|
||||
WriteParam(aMsg, length);
|
||||
|
||||
if (sUseWriteBytes) {
|
||||
int pickledLength = 0;
|
||||
MOZ_RELEASE_ASSERT(ByteLengthIsValid(length, sizeof(E), &pickledLength));
|
||||
aMsg->WriteBytes(aParam.begin(), pickledLength);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const E& elem : aParam) {
|
||||
WriteParam(aMsg, elem);
|
||||
}
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint32_t length;
|
||||
if (!ReadParam(aMsg, aIter, &length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sUseWriteBytes) {
|
||||
int pickledLength = 0;
|
||||
if (!ByteLengthIsValid(length, sizeof(E), &pickledLength)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aResult->resizeUninitialized(length)) {
|
||||
// So that OOM failure shows up as OOM crash instead of IPC FatalError.
|
||||
NS_ABORT_OOM(length * sizeof(E));
|
||||
}
|
||||
|
||||
E* elements = aResult->begin();
|
||||
return aMsg->ReadBytesInto(aIter, elements, pickledLength);
|
||||
}
|
||||
|
||||
// Each ReadParam<E> may read more than 1 byte each; this is an attempt
|
||||
// to minimally validate that the length isn't much larger than what's
|
||||
// actually available in aMsg.
|
||||
if (!aMsg->HasBytesAvailable(aIter, length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aResult->resize(length)) {
|
||||
// So that OOM failure shows up as OOM crash instead of IPC FatalError.
|
||||
NS_ABORT_OOM(length * sizeof(E));
|
||||
}
|
||||
|
||||
for (uint32_t index = 0; index < length; ++index) {
|
||||
if (!ReadParam(aMsg, aIter, &((*aResult)[index]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
for (uint32_t index = 0, len = aParam.length(); index < len; ++index) {
|
||||
if (index) {
|
||||
aLog->append(L" ");
|
||||
}
|
||||
LogParam(aParam[index], aLog);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename E>
|
||||
struct ParamTraits<std::vector<E>> {
|
||||
typedef std::vector<E> paramType;
|
||||
|
||||
// We write arrays of integer or floating-point data using a single pickling
|
||||
// call, rather than writing each element individually. We deliberately do
|
||||
// not use mozilla::IsPod here because it is perfectly reasonable to have
|
||||
// a data structure T for which IsPod<T>::value is true, yet also have a
|
||||
// ParamTraits<T> specialization.
|
||||
static const bool sUseWriteBytes =
|
||||
(mozilla::IsIntegral<E>::value || mozilla::IsFloatingPoint<E>::value);
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
uint32_t length = aParam.size();
|
||||
WriteParam(aMsg, length);
|
||||
|
||||
if (sUseWriteBytes) {
|
||||
int pickledLength = 0;
|
||||
MOZ_RELEASE_ASSERT(ByteLengthIsValid(length, sizeof(E), &pickledLength));
|
||||
aMsg->WriteBytes(aParam.data(), pickledLength);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const E& elem : aParam) {
|
||||
WriteParam(aMsg, elem);
|
||||
}
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint32_t length;
|
||||
if (!ReadParam(aMsg, aIter, &length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sUseWriteBytes) {
|
||||
int pickledLength = 0;
|
||||
if (!ByteLengthIsValid(length, sizeof(E), &pickledLength)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->resize(length);
|
||||
|
||||
E* elements = aResult->data();
|
||||
return aMsg->ReadBytesInto(aIter, elements, pickledLength);
|
||||
}
|
||||
|
||||
// Each ReadParam<E> may read more than 1 byte each; this is an attempt
|
||||
// to minimally validate that the length isn't much larger than what's
|
||||
// actually available in aMsg.
|
||||
if (!aMsg->HasBytesAvailable(aIter, length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->resize(length);
|
||||
|
||||
for (uint32_t index = 0; index < length; ++index) {
|
||||
if (!ReadParam(aMsg, aIter, &((*aResult)[index]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
for (uint32_t index = 0, len = aParam.size(); index < len; ++index) {
|
||||
if (index) {
|
||||
aLog->append(L" ");
|
||||
}
|
||||
LogParam(aParam[index], aLog);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<float> {
|
||||
typedef float paramType;
|
||||
|
Loading…
Reference in New Issue
Block a user