COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
SequenceSerLengthFieldPrefix.h
1//
2// Copyright 2017 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: MPL-2.0
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#pragma once
11
12#include "comms/Assert.h"
13#include "comms/ErrorStatus.h"
14
15#include <algorithm>
16#include <cstddef>
17#include <iterator>
18#include <utility>
19
20namespace comms
21{
22
23namespace field
24{
25
26namespace adapter
27{
28
29template <typename TLenField, comms::ErrorStatus TStatus, typename TBase>
30class SequenceSerLengthFieldPrefix : public TBase
31{
32 using BaseImpl = TBase;
33 using LenField = TLenField;
34
35 static const std::size_t MaxAllowedLength =
36 static_cast<std::size_t>(LenField::maxValue());
37
38 static_assert(!LenField::isVersionDependent(),
39 "Prefix fields must not be version dependent");
40
41public:
42 using ValueType = typename BaseImpl::ValueType;
43 using ElementType = typename BaseImpl::ElementType;
44
46
47 explicit SequenceSerLengthFieldPrefix(const ValueType& val)
48 : BaseImpl(val)
49 {
50 }
51
52 explicit SequenceSerLengthFieldPrefix(ValueType&& val)
53 : BaseImpl(std::move(val))
54 {
55 }
56
57 SequenceSerLengthFieldPrefix(const SequenceSerLengthFieldPrefix&) = default;
58 SequenceSerLengthFieldPrefix(SequenceSerLengthFieldPrefix&&) = default;
59 SequenceSerLengthFieldPrefix& operator=(const SequenceSerLengthFieldPrefix&) = default;
60 SequenceSerLengthFieldPrefix& operator=(SequenceSerLengthFieldPrefix&&) = default;
61
62 std::size_t length() const
63 {
64 auto valLength = BaseImpl::length();
65 LenField lenField;
66 lenField.setValue(std::min(valLength, std::size_t(MaxAllowedLength)));
67 return lenField.length() + valLength;
68 }
69
70 static constexpr std::size_t minLength()
71 {
72 return LenField::minLength();
73 }
74
75 static constexpr std::size_t maxLength()
76 {
77 return LenField::maxLength() + BaseImpl::maxLength();
78 }
79
80 bool valid() const
81 {
82 if ((!BaseImpl::valid()) || (!canWrite())) {
83 return false;
84 }
85
86 LenField lenField;
87 auto lenValue = std::min(BaseImpl::length(), std::size_t(MaxAllowedLength));
88 lenField.setValue(lenValue);
89 return lenField.valid();
90 }
91
92 template <typename TIter>
93 comms::ErrorStatus read(TIter& iter, std::size_t len)
94 {
95 auto fromIter = iter;
96 LenField lenField;
97 auto es = lenField.read(iter, len);
99 return es;
100 }
101
102 auto diff = static_cast<std::size_t>(std::distance(fromIter, iter));
103 COMMS_ASSERT(diff <= len);
104 len -= diff;
105 auto remLen = static_cast<std::size_t>(lenField.getValue());
106 if (len < remLen) {
107 return TStatus;
108 }
109
110 es = BaseImpl::read(iter, remLen);
112 return TStatus;
113 }
114
115 return es;
116 }
117
118 static constexpr bool hasReadNoStatus()
119 {
120 return false;
121 }
122
123 template <typename TIter>
124 void readNoStatus(TIter& iter) = delete;
125
126 bool canWrite() const
127 {
128 if (!BaseImpl::canWrite()) {
129 return false;
130 }
131
132 auto len = BaseImpl::length();
133 if (MaxAllowedLength < len) {
134 return false;
135 }
136
137 LenField lenField;
138 lenField.setValue(len);
139 return lenField.canWrite();
140 }
141
142 template <typename TIter>
143 comms::ErrorStatus write(TIter& iter, std::size_t len) const
144 {
145 if (!canWrite()) {
147 }
148
149 auto lenVal = BaseImpl::length();
150 LenField lenField;
151 lenField.setValue(lenVal);
152 auto es = lenField.write(iter, len);
153 if (es != comms::ErrorStatus::Success) {
154 return es;
155 }
156
157 COMMS_ASSERT(lenField.length() <= len);
158 return BaseImpl::write(iter, lenVal);
159 }
160
161 static constexpr bool hasWriteNoStatus()
162 {
163 return false;
164 }
165
166 template <typename TIter>
167 void writeNoStatus(TIter& iter) const = delete;
168};
169
170} // namespace adapter
171
172} // namespace field
173
174} // namespace comms
175
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
This file contain definition of error statuses used by comms module.
comms::option::def::SequenceSerLengthFieldPrefix< TField, TReadErrorStatus > SequenceSerLengthFieldPrefix
Same as comms::option::def::SequenceSerLengthFieldPrefix.
Definition options.h:1568
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:19
@ Success
Used to indicate successful outcome of the operation.
@ InvalidMsgData
Used to indicate that a message has invalid data.
STL namespace.