[ox/model] Fix infinite recursion caused by have a vector of the same type in ModelValue

This commit is contained in:
Gary Talent 2023-12-22 19:44:04 -06:00
parent 80d0df2f46
commit ef6e3af735
5 changed files with 33 additions and 22 deletions

View File

@ -265,10 +265,10 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
// set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
oxRequire(len, arrayLength(name, false));
val->resize(len);
oxReturnError(ox::resizeVector(*val, len));
return field(name, val->data(), val->size());
}
val->resize(0);
oxReturnError(ox::resizeVector(*val, 0));
}
++m_field;
return {};
@ -302,12 +302,12 @@ template<typename U, bool force>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U, force> val) noexcept {
if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val.get()) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
auto reader = child("", ox::Optional<int>(ox::in_place_t{}, val.idx()));
auto reader = child("", ox::Optional<int>(ox::in_place, val.idx()));
oxReturnError(model(reader.interface(), val.get()));
}
}
++m_field;
return OxError(0);
return {};
}
template<Reader_c Reader>

View File

@ -261,15 +261,16 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexce
} else {
bool fieldSet = false;
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
oxReturnError(model(&handler, val));
oxReturnError(writer.finalize());
fieldSet = true;
fieldSet = writeIdx != m_writer.tellp();
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return OxError(0);
return {};
}
}
@ -278,15 +279,16 @@ template<typename U, bool force>
constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept {
bool fieldSet = false;
if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx()));
ModelHandlerInterface handler{&writer};
oxReturnError(model(&handler, val.get()));
oxReturnError(writer.finalize());
fieldSet = true;
fieldSet = writeIdx != m_writer.tellp();
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return OxError(0);
return {};
}
template<Writer_c Writer>
@ -297,15 +299,16 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::s
// write the length
const auto arrLen = mc::encodeInteger(len);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer};
oxReturnError(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
// write the array
for (std::size_t i = 0; i < len; i++) {
for (std::size_t i = 0; i < len; ++i) {
oxReturnError(handler.field("", &val[i]));
}
oxReturnError(writer.finalize());
fieldSet = true;
fieldSet = writeIdx != m_writer.tellp();
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
@ -337,7 +340,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
return handler.field("", value);
};
// write the array
for (std::size_t i = 0; i < len; i++) {
for (std::size_t i = 0; i < len; ++i) {
auto const&key = keys[i];
oxReturnError(loopBody(handler, key, *val));
}

View File

@ -196,7 +196,6 @@ class ModelHandlerInterface {
constexpr auto handler() noexcept {
return m_handler;
}
};
template<typename Handler, ox::OpType opType_v = Handler::opType()>
@ -215,7 +214,16 @@ class ModelHandlerBase {
static constexpr ox::OpType opType() noexcept {
return opType_v;
}
};
constexpr ox::Error resizeVector(auto &vec, size_t sz) {
if constexpr(ox::is_same_v<decltype(vec.resize(0)), ox::Error>) {
return vec.resize(sz);
} else {
vec.resize(sz);
return {};
}
}
}

View File

@ -202,7 +202,8 @@ class ModelValue {
class ModelValueVector {
private:
Vector<ModelValue> m_vec;
ModelValue m_templateValue;
const DescriptorType *m_type = nullptr;
int m_typeSubscriptLevels = 0;
String m_typeName;
int m_typeVersion = 0;
@ -227,14 +228,15 @@ class ModelValueVector {
return m_vec.data();
}
constexpr void resize(std::size_t sz) noexcept {
constexpr ox::Error resize(std::size_t sz) noexcept {
const auto oldSz = m_vec.size();
m_vec.resize(sz);
if (sz > oldSz) {
for (auto i = oldSz; i < sz; ++i) {
m_vec[i] = m_templateValue;
oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels));
}
}
return {};
}
[[nodiscard]]
@ -248,7 +250,9 @@ class ModelValueVector {
}
constexpr Error setType(const DescriptorType *type, int subscriptLevels) noexcept {
return m_templateValue.setType(type, subscriptLevels);
m_type = type;
m_typeSubscriptLevels = subscriptLevels;
return {};
}
[[nodiscard]]
@ -1089,14 +1093,12 @@ constexpr ModelValueVector::ModelValueVector(const ModelValueVector &other) noex
for (auto &v : other.m_vec) {
m_vec.emplace_back(v);
}
m_templateValue = other.m_templateValue;
m_typeName = other.m_typeName;
m_typeVersion = other.m_typeVersion;
}
constexpr ModelValueVector::ModelValueVector(ModelValueVector &&other) noexcept {
m_vec = std::move(other.m_vec);
m_templateValue = std::move(other.m_templateValue);
m_typeName = std::move(other.m_typeName);
m_typeVersion = other.m_typeVersion;
}
@ -1108,7 +1110,6 @@ constexpr ModelValueVector &ModelValueVector::operator=(const ModelValueVector &
for (auto &v : other.m_vec) {
m_vec.emplace_back(v);
}
m_templateValue = other.m_templateValue;
m_typeName = other.m_typeName;
m_typeVersion = other.m_typeVersion;
return *this;
@ -1119,7 +1120,6 @@ constexpr ModelValueVector &ModelValueVector::operator=(ModelValueVector &&other
return *this;
}
m_vec = std::move(other.m_vec);
m_templateValue = std::move(other.m_templateValue);
m_typeName = std::move(other.m_typeName);
m_typeVersion = other.m_typeVersion;
return *this;

View File

@ -147,7 +147,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
if constexpr(isVector_v<T>) {
const auto &srcVal = value(key);
const auto srcSize = srcVal.size();
val->resize(srcSize);
oxReturnError(ox::resizeVector(*val, srcSize));
err = field(key, val->data(), val->size());
} else if constexpr(isArray_v<T>) {
const auto &srcVal = value(key);