20
20
#include < array>
21
21
#include < cstddef>
22
22
#include < limits>
23
- #include < numeric>
24
23
#include < type_traits>
25
24
26
25
#include < nop/base/encoding.h>
80
79
81
80
namespace nop {
82
81
83
- // Common glue shared by integral and non-integral LogicalBuffer encodings.
84
- template <typename T>
85
- struct LogicalBufferCommon {
86
- template <typename Writer>
87
- static constexpr Status<void > WriteUnbounded (const T& value, Writer* writer) {
88
- EncodingByte prefix = Encoding<T>::Prefix (value);
89
- auto status = writer->Write (static_cast <std::uint8_t >(prefix));
90
- if (!status)
91
- return status;
92
- else
93
- return Encoding<T>::WriteUnboundedPayload (prefix, value, writer);
94
- }
95
-
96
- template <typename Reader>
97
- static constexpr Status<void > ReadUnbounded (T* value, Reader* reader) {
98
- std::uint8_t prefix_byte = 0 ;
99
- auto status = reader->Read (&prefix_byte);
100
- if (!status)
101
- return status;
102
-
103
- const EncodingByte prefix = static_cast <EncodingByte>(prefix_byte);
104
- if (Encoding<T>::Match (prefix))
105
- return Encoding<T>::ReadUnboundedPayload (prefix, value, reader);
106
- else
107
- return ErrorStatus::UnexpectedEncodingType;
108
- }
109
- };
110
-
111
82
// Encoding type that handles non-integral element types. Logical buffers of
112
83
// non-integral element types are encoded the same as non-integral arrays using
113
84
// the ARRAY encoding.
114
- template <typename BufferType, typename SizeType>
85
+ template <typename BufferType, typename SizeType, bool IsUnbounded >
115
86
struct Encoding <
116
- LogicalBuffer<BufferType, SizeType>,
87
+ LogicalBuffer<BufferType, SizeType, IsUnbounded >,
117
88
EnableIfNotIntegral<typename ArrayTraits<BufferType>::ElementType>>
118
- : EncodingIO<LogicalBuffer<BufferType, SizeType>>,
119
- LogicalBufferCommon<LogicalBuffer<BufferType, SizeType>> {
120
- using Type = LogicalBuffer<BufferType, SizeType>;
121
- using ValueType =
122
- std::remove_const_t <typename ArrayTraits<BufferType>::ElementType>;
123
- enum : std::size_t { Length = ArrayTraits<BufferType>::Length };
89
+ : EncodingIO<LogicalBuffer<BufferType, SizeType, IsUnbounded>> {
90
+ using Type = LogicalBuffer<BufferType, SizeType, IsUnbounded>;
91
+ using ValueType = std::remove_const_t <typename Type::ValueType>;
92
+ enum : std::size_t { Length = Type::Length };
124
93
125
94
static constexpr EncodingByte Prefix (const Type& /* value*/ ) {
126
95
return EncodingByte::Array;
127
96
}
128
97
129
98
static constexpr std::size_t Size (const Type& value) {
99
+ std::size_t element_size_sum = 0 ;
100
+ for (const ValueType& element : value)
101
+ element_size_sum += Encoding<ValueType>::Size (element);
102
+
130
103
return BaseEncodingSize (Prefix (value)) +
131
- Encoding<SizeType>::Size (value.size ()) +
132
- std::accumulate (
133
- std::begin (value), std::end (value), 0U ,
134
- [](const std::size_t & sum, const ValueType& element) {
135
- return sum + Encoding<ValueType>::Size (element);
136
- });
104
+ Encoding<SizeType>::Size (value.size ()) + element_size_sum;
137
105
}
138
106
139
107
static constexpr bool Match (EncodingByte prefix) {
@@ -145,7 +113,7 @@ struct Encoding<
145
113
const Type& value,
146
114
Writer* writer) {
147
115
const SizeType size = static_cast <SizeType>(value.size ());
148
- if (size > Length)
116
+ if (!IsUnbounded && size > Length)
149
117
return ErrorStatus::InvalidContainerLength;
150
118
151
119
auto status = Encoding<SizeType>::Write (size, writer);
@@ -161,32 +129,14 @@ struct Encoding<
161
129
return {};
162
130
}
163
131
164
- template <typename Writer>
165
- static constexpr Status<void > WriteUnboundedPayload (EncodingByte /* prefix*/ ,
166
- const Type& value,
167
- Writer* writer) {
168
- const SizeType size = static_cast <SizeType>(value.size ());
169
- auto status = Encoding<SizeType>::Write (size, writer);
170
- if (!status)
171
- return status;
172
-
173
- for (SizeType i = 0 ; i < size; i++) {
174
- status = Encoding<ValueType>::Write (value[i], writer);
175
- if (!status)
176
- return status;
177
- }
178
-
179
- return {};
180
- }
181
-
182
132
template <typename Reader>
183
133
static constexpr Status<void > ReadPayload (EncodingByte /* prefix*/ ,
184
134
Type* value, Reader* reader) {
185
135
SizeType size;
186
136
auto status = Encoding<SizeType>::Read (&size, reader);
187
137
if (!status)
188
138
return status;
189
- else if (size > Length)
139
+ else if (!IsUnbounded && size > Length)
190
140
return ErrorStatus::InvalidContainerLength;
191
141
192
142
for (SizeType i = 0 ; i < size; i++) {
@@ -198,39 +148,18 @@ struct Encoding<
198
148
value->size () = size;
199
149
return {};
200
150
}
201
-
202
- template <typename Reader>
203
- static constexpr Status<void > ReadUnboundedPayload (EncodingByte /* prefix*/ ,
204
- Type* value,
205
- Reader* reader) {
206
- SizeType size;
207
- auto status = Encoding<SizeType>::Read (&size, reader);
208
- if (!status)
209
- return status;
210
-
211
- for (SizeType i = 0 ; i < size; i++) {
212
- status = Encoding<ValueType>::Read (&(*value)[i], reader);
213
- if (!status)
214
- return status;
215
- }
216
-
217
- value->size () = size;
218
- return {};
219
- }
220
151
};
221
152
222
153
// Encoding type that handles integral element types. Logical buffers of
223
154
// integral element types are encoded the same as arrays with integral elements
224
155
// using the BINARY encoding.
225
- template <typename BufferType, typename SizeType>
226
- struct Encoding <LogicalBuffer<BufferType, SizeType>,
156
+ template <typename BufferType, typename SizeType, bool IsUnbounded >
157
+ struct Encoding <LogicalBuffer<BufferType, SizeType, IsUnbounded >,
227
158
EnableIfIntegral<typename ArrayTraits<BufferType>::ElementType>>
228
- : EncodingIO<LogicalBuffer<BufferType, SizeType>>,
229
- LogicalBufferCommon<LogicalBuffer<BufferType, SizeType>> {
230
- using Type = LogicalBuffer<BufferType, SizeType>;
231
- using ValueType =
232
- std::remove_const_t <typename ArrayTraits<BufferType>::ElementType>;
233
- enum : std::size_t { Length = ArrayTraits<BufferType>::Length };
159
+ : EncodingIO<LogicalBuffer<BufferType, SizeType, IsUnbounded>> {
160
+ using Type = LogicalBuffer<BufferType, SizeType, IsUnbounded>;
161
+ using ValueType = std::remove_const_t <typename Type::ValueType>;
162
+ enum : std::size_t { Length = Type::Length };
234
163
235
164
static constexpr EncodingByte Prefix (const Type& /* value*/ ) {
236
165
return EncodingByte::Binary;
@@ -251,7 +180,7 @@ struct Encoding<LogicalBuffer<BufferType, SizeType>,
251
180
const Type& value,
252
181
Writer* writer) {
253
182
const SizeType size = value.size ();
254
- if (size > Length)
183
+ if (!IsUnbounded && size > Length)
255
184
return ErrorStatus::InvalidContainerLength;
256
185
257
186
auto status = Encoding<SizeType>::Write (size * sizeof (ValueType), writer);
@@ -261,26 +190,14 @@ struct Encoding<LogicalBuffer<BufferType, SizeType>,
261
190
return writer->Write (value.begin (), value.end ());
262
191
}
263
192
264
- template <typename Writer>
265
- static constexpr Status<void > WriteUnboundedPayload (EncodingByte /* prefix*/ ,
266
- const Type& value,
267
- Writer* writer) {
268
- const SizeType size = value.size ();
269
- auto status = Encoding<SizeType>::Write (size * sizeof (ValueType), writer);
270
- if (!status)
271
- return status;
272
-
273
- return writer->Write (value.begin (), value.end ());
274
- }
275
-
276
193
template <typename Reader>
277
194
static constexpr Status<void > ReadPayload (EncodingByte /* prefix*/ ,
278
195
Type* value, Reader* reader) {
279
196
SizeType size_bytes = 0 ;
280
197
auto status = Encoding<SizeType>::Read (&size_bytes, reader);
281
198
if (!status) {
282
199
return status;
283
- } else if (size_bytes > Length * sizeof (ValueType) ||
200
+ } else if ((!IsUnbounded && size_bytes > Length * sizeof (ValueType) ) ||
284
201
size_bytes % sizeof (ValueType) != 0 ) {
285
202
return ErrorStatus::InvalidContainerLength;
286
203
}
@@ -289,22 +206,6 @@ struct Encoding<LogicalBuffer<BufferType, SizeType>,
289
206
value->size () = size;
290
207
return reader->Read (value->begin (), value->end ());
291
208
}
292
-
293
- template <typename Reader>
294
- static constexpr Status<void > ReadUnboundedPayload (EncodingByte /* prefix*/ ,
295
- Type* value,
296
- Reader* reader) {
297
- SizeType size_bytes = 0 ;
298
- auto status = Encoding<SizeType>::Read (&size_bytes, reader);
299
- if (!status)
300
- return status;
301
- else if (size_bytes % sizeof (ValueType) != 0 )
302
- return ErrorStatus::InvalidContainerLength;
303
-
304
- const SizeType size = size_bytes / sizeof (ValueType);
305
- value->size () = size;
306
- return reader->Read (value->begin (), value->end ());
307
- }
308
209
};
309
210
310
211
} // namespace nop
0 commit comments