Skip to content

Commit

Permalink
Fixing partial read when RemLengthMemberField adapter is in use.
Browse files Browse the repository at this point in the history
  • Loading branch information
arobenko committed Jun 18, 2024
1 parent 5dba203 commit e7d01eb
Showing 1 changed file with 26 additions and 33 deletions.
59 changes: 26 additions & 33 deletions include/comms/field/adapter/RemLengthMemberField.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,45 +97,31 @@ class RemLengthMemberField : public TBase
template <typename TIter>
ErrorStatus read(TIter& iter, std::size_t len)
{
return readFromUntilInternal<0, std::tuple_size<ValueType>::value>(iter, len, LocalTag<>());
return readFromUntilAndUpdateLen<0, std::tuple_size<ValueType>::value>(iter, len);
}

template <std::size_t TFromIdx, typename TIter>
ErrorStatus readFrom(TIter& iter, std::size_t len)
{
return readFromAndUpdateLen<TFromIdx>(iter, len);
return readFromUntilAndUpdateLen<TFromIdx, std::tuple_size<ValueType>::value>(iter, len);
}

template <std::size_t TFromIdx, typename TIter>
ErrorStatus readFromAndUpdateLen(TIter& iter, std::size_t& len)
{
using Tag =
typename comms::util::LazyShallowConditional<
TLenFieldIdx < TFromIdx
>::template Type<
BaseRedirectTag,
LocalTag
>;
return readFromUntilInternal<TFromIdx, std::tuple_size<ValueType>::value>(iter, len, Tag());
return readFromAndUpdateLen<TFromIdx, std::tuple_size<ValueType>::value>(iter, len);
}

template <std::size_t TUntilIdx, typename TIter>
ErrorStatus readUntil(TIter& iter, std::size_t len)
{
return readUntilAndUpdateLen<TUntilIdx>(iter, len);
return readFromUntilAndUpdateLen<0U, TUntilIdx>(iter, len);
}

template <std::size_t TUntilIdx, typename TIter>
ErrorStatus readUntilAndUpdateLen(TIter& iter, std::size_t& len)
{
using Tag =
typename comms::util::LazyShallowConditional<
TUntilIdx <= TLenFieldIdx
>::template Type<
BaseRedirectTag,
LocalTag
>;
return readFromUntilInternal<0, TUntilIdx>(iter, len, Tag());
return readFromUntilAndUpdateLen<0, TUntilIdx>(iter, len);
}

template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TIter>
Expand All @@ -149,7 +135,7 @@ class RemLengthMemberField : public TBase
{
using Tag =
typename comms::util::LazyShallowConditional<
(TLenFieldIdx < TFromIdx) || (TUntilIdx <= TLenFieldIdx)
(TUntilIdx <= TLenFieldIdx)
>::template Type<
BaseRedirectTag,
LocalTag
Expand Down Expand Up @@ -226,7 +212,6 @@ class RemLengthMemberField : public TBase
template <typename... TParams>
using LocalTag = comms::details::tag::Tag2<>;


template <std::size_t TFromIdx, typename... TParams>
static constexpr std::size_t maxLengthFromInternal(BaseRedirectTag<TParams...>)
{
Expand Down Expand Up @@ -272,12 +257,13 @@ class RemLengthMemberField : public TBase
template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TIter, typename... TParams>
ErrorStatus readFromUntilInternal(TIter& iter, std::size_t& len, LocalTag<TParams...>)
{
static_assert(TFromIdx <= TLenFieldIdx, "Invalid function invocation");
static_assert(TLenFieldIdx < TUntilIdx, "Invalid function invocation");

auto es = BaseImpl::template readFromUntilAndUpdateLen<TFromIdx, TLenFieldIdx>(iter, len);
if (es != comms::ErrorStatus::Success) {
return es;
auto es = comms::ErrorStatus::Success;
if (TFromIdx < TLenFieldIdx) {
es = BaseImpl::template readFromUntilAndUpdateLen<TFromIdx, TLenFieldIdx>(iter, len);
if (es != comms::ErrorStatus::Success) {
return es;
}
}

auto beforeLenReadIter = iter;
Expand All @@ -288,7 +274,6 @@ class RemLengthMemberField : public TBase
return es;
}

auto afterLenReadIter = iter;
auto lenFieldLen = static_cast<std::size_t>(std::distance(beforeLenReadIter, iter));
COMMS_ASSERT(lenFieldLen <= len);
len -= lenFieldLen;
Expand All @@ -298,14 +283,22 @@ class RemLengthMemberField : public TBase
return comms::ErrorStatus::NotEnoughData;
}

es = BaseImpl::template readFromUntil<TLenFieldIdx + 1, TUntilIdx>(iter, reqLen);
if (es == comms::ErrorStatus::Success) {
iter = afterLenReadIter;
std::advance(iter, reqLen);
len -= reqLen;
auto remLen = reqLen;
es = BaseImpl::template readFromUntilAndUpdateLen<TLenFieldIdx + 1, TUntilIdx>(iter, remLen);
auto consumed = reqLen - remLen;
len -= consumed;

if (es != comms::ErrorStatus::Success) {
return es;
}

if (std::tuple_size<ValueType>::value <= TUntilIdx) {
len -= remLen;
std::advance(iter, remLen);
}

return es;
}
}

bool refreshLengthInternal()
{
Expand Down

0 comments on commit e7d01eb

Please sign in to comment.