Hazelcast C++ Client
Hazelcast C++ Client Library
compact.cpp
1 /*
2  * Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <utility>
18 #include "hazelcast/client/serialization/serialization.h"
19 #include "hazelcast/util/Bits.h"
20 namespace hazelcast {
21 namespace client {
22 namespace serialization {
23 
24 compact_writer::compact_writer(
25  pimpl::default_compact_writer* default_compact_writer)
26  : default_compact_writer(default_compact_writer)
27  , schema_writer(nullptr)
28 {}
29 compact_writer::compact_writer(pimpl::schema_writer* schema_writer)
30  : default_compact_writer(nullptr)
31  , schema_writer(schema_writer)
32 {}
33 
34 void
35 compact_writer::write_boolean(const std::string& field_name, bool value)
36 {
37  if (default_compact_writer) {
38  default_compact_writer->write_boolean(field_name, value);
39  } else {
40  schema_writer->add_field(field_name, pimpl::field_kind::BOOLEAN);
41  }
42 }
43 void
44 compact_writer::write_int8(const std::string& field_name, int8_t value)
45 {
46  if (default_compact_writer) {
47  default_compact_writer->write_int8(field_name, value);
48  } else {
49  schema_writer->add_field(field_name, pimpl::field_kind::INT8);
50  }
51 }
52 
53 void
54 compact_writer::write_int16(const std::string& field_name, int16_t value)
55 {
56  if (default_compact_writer) {
57  default_compact_writer->write_int16(field_name, value);
58  } else {
59  schema_writer->add_field(field_name, pimpl::field_kind::INT16);
60  }
61 }
62 
63 void
64 compact_writer::write_int32(const std::string& field_name, int32_t value)
65 {
66  if (default_compact_writer != nullptr) {
67  default_compact_writer->write_int32(field_name, value);
68  } else {
69  schema_writer->add_field(field_name, pimpl::field_kind::INT32);
70  }
71 }
72 
73 void
74 compact_writer::write_int64(const std::string& field_name, int64_t value)
75 {
76  if (default_compact_writer != nullptr) {
77  default_compact_writer->write_int64(field_name, value);
78  } else {
79  schema_writer->add_field(field_name, pimpl::field_kind::INT64);
80  }
81 }
82 
83 void
84 compact_writer::write_float32(const std::string& field_name, float value)
85 {
86  if (default_compact_writer != nullptr) {
87  default_compact_writer->write_float32(field_name, value);
88  } else {
89  schema_writer->add_field(field_name, pimpl::field_kind::FLOAT32);
90  }
91 }
92 
93 void
94 compact_writer::write_float64(const std::string& field_name, double value)
95 {
96  if (default_compact_writer != nullptr) {
97  default_compact_writer->write_float64(field_name, value);
98  } else {
99  schema_writer->add_field(field_name, pimpl::field_kind::FLOAT64);
100  }
101 }
102 
103 void
104 compact_writer::write_string(const std::string& field_name,
105  const boost::optional<std::string>& value)
106 {
107  if (default_compact_writer != nullptr) {
108  default_compact_writer->write_string(field_name, value);
109  } else {
110  schema_writer->add_field(field_name, pimpl::field_kind::STRING);
111  }
112 }
113 
114 void
115 compact_writer::write_decimal(const std::string& field_name,
116  const boost::optional<big_decimal>& value)
117 {
118  if (default_compact_writer != nullptr) {
119  default_compact_writer->write_decimal(field_name, value);
120  } else {
121  schema_writer->add_field(field_name, pimpl::field_kind::DECIMAL);
122  }
123 }
124 
125 void
126 compact_writer::write_time(
127  const std::string& field_name,
128  const boost::optional<hazelcast::client::local_time>& value)
129 {
130  if (default_compact_writer != nullptr) {
131  default_compact_writer->write_time(field_name, value);
132  } else {
133  schema_writer->add_field(field_name, pimpl::field_kind::TIME);
134  }
135 }
136 
137 void
138 compact_writer::write_date(
139  const std::string& field_name,
140  const boost::optional<hazelcast::client::local_date>& value)
141 {
142  if (default_compact_writer != nullptr) {
143  default_compact_writer->write_date(field_name, value);
144  } else {
145  schema_writer->add_field(field_name, pimpl::field_kind::DATE);
146  }
147 }
148 
149 void
150 compact_writer::write_timestamp(
151  const std::string& field_name,
152  const boost::optional<hazelcast::client::local_date_time>& value)
153 {
154  if (default_compact_writer != nullptr) {
155  default_compact_writer->write_timestamp(field_name, value);
156  } else {
157  schema_writer->add_field(field_name, pimpl::field_kind::TIMESTAMP);
158  }
159 }
160 
161 void
162 compact_writer::write_timestamp_with_timezone(
163  const std::string& field_name,
164  const boost::optional<hazelcast::client::offset_date_time>& value)
165 {
166  if (default_compact_writer != nullptr) {
167  default_compact_writer->write_timestamp_with_timezone(field_name,
168  value);
169  } else {
170  schema_writer->add_field(field_name,
171  pimpl::field_kind::TIMESTAMP_WITH_TIMEZONE);
172  }
173 }
174 
175 void
176 compact_writer::write_array_of_boolean(
177  const std::string& field_name,
178  const boost::optional<std::vector<bool>>& value)
179 {
180  if (default_compact_writer != nullptr) {
181  default_compact_writer->write_array_of_boolean(field_name, value);
182  } else {
183  schema_writer->add_field(field_name,
184  pimpl::field_kind::ARRAY_OF_BOOLEAN);
185  }
186 }
187 
188 void
189 compact_writer::write_array_of_int8(
190  const std::string& field_name,
191  const boost::optional<std::vector<int8_t>>& value)
192 {
193  if (default_compact_writer != nullptr) {
194  default_compact_writer->write_array_of_int8(field_name, value);
195  } else {
196  schema_writer->add_field(field_name, pimpl::field_kind::ARRAY_OF_INT8);
197  }
198 }
199 
200 void
201 compact_writer::write_array_of_int16(
202  const std::string& field_name,
203  const boost::optional<std::vector<int16_t>>& value)
204 {
205  if (default_compact_writer != nullptr) {
206  default_compact_writer->write_array_of_int16(field_name, value);
207  } else {
208  schema_writer->add_field(field_name, pimpl::field_kind::ARRAY_OF_INT16);
209  }
210 }
211 
212 void
213 compact_writer::write_array_of_int32(
214  const std::string& field_name,
215  const boost::optional<std::vector<int32_t>>& value)
216 {
217  if (default_compact_writer != nullptr) {
218  default_compact_writer->write_array_of_int32(field_name, value);
219  } else {
220  schema_writer->add_field(field_name, pimpl::field_kind::ARRAY_OF_INT32);
221  }
222 }
223 
224 void
225 compact_writer::write_array_of_int64(
226  const std::string& field_name,
227  const boost::optional<std::vector<int64_t>>& value)
228 {
229  if (default_compact_writer != nullptr) {
230  default_compact_writer->write_array_of_int64(field_name, value);
231  } else {
232  schema_writer->add_field(field_name, pimpl::field_kind::ARRAY_OF_INT64);
233  }
234 }
235 
236 void
237 compact_writer::write_array_of_float32(
238  const std::string& field_name,
239  const boost::optional<std::vector<float>>& value)
240 {
241  if (default_compact_writer != nullptr) {
242  default_compact_writer->write_array_of_float32(field_name, value);
243  } else {
244  schema_writer->add_field(field_name,
245  pimpl::field_kind::ARRAY_OF_FLOAT32);
246  }
247 }
248 
249 void
250 compact_writer::write_array_of_float64(
251  const std::string& field_name,
252  const boost::optional<std::vector<double>>& value)
253 {
254  if (default_compact_writer != nullptr) {
255  default_compact_writer->write_array_of_float64(field_name, value);
256  } else {
257  schema_writer->add_field(field_name,
258  pimpl::field_kind::ARRAY_OF_FLOAT64);
259  }
260 }
261 
262 void
263 compact_writer::write_array_of_string(
264  const std::string& field_name,
265  const boost::optional<std::vector<boost::optional<std::string>>>& value)
266 {
267  if (default_compact_writer != nullptr) {
268  default_compact_writer->write_array_of_string(field_name, value);
269  } else {
270  schema_writer->add_field(field_name,
271  pimpl::field_kind::ARRAY_OF_STRING);
272  }
273 }
274 
275 void
276 compact_writer::write_array_of_decimal(
277  const std::string& field_name,
278  const boost::optional<std::vector<boost::optional<big_decimal>>>& value)
279 {
280  if (default_compact_writer != nullptr) {
281  default_compact_writer->write_array_of_decimal(field_name, value);
282  } else {
283  schema_writer->add_field(field_name,
284  pimpl::field_kind::ARRAY_OF_DECIMAL);
285  }
286 }
287 
288 void
289 compact_writer::write_array_of_time(
290  const std::string& field_name,
291  const boost::optional<std::vector<boost::optional<local_time>>>& value)
292 {
293  if (default_compact_writer != nullptr) {
294  default_compact_writer->write_array_of_time(field_name, value);
295  } else {
296  schema_writer->add_field(field_name, pimpl::field_kind::ARRAY_OF_TIME);
297  }
298 }
299 
300 void
301 compact_writer::write_array_of_date(
302  const std::string& field_name,
303  const boost::optional<std::vector<boost::optional<local_date>>>& value)
304 {
305  if (default_compact_writer != nullptr) {
306  default_compact_writer->write_array_of_date(field_name, value);
307  } else {
308  schema_writer->add_field(field_name, pimpl::field_kind::ARRAY_OF_DATE);
309  }
310 }
311 
312 void
313 compact_writer::write_array_of_timestamp(
314  const std::string& field_name,
315  const boost::optional<std::vector<boost::optional<local_date_time>>>& value)
316 {
317  if (default_compact_writer != nullptr) {
318  default_compact_writer->write_array_of_timestamp(field_name, value);
319  } else {
320  schema_writer->add_field(field_name,
321  pimpl::field_kind::ARRAY_OF_TIMESTAMP);
322  }
323 }
324 
325 void
326 compact_writer::write_array_of_timestamp_with_timezone(
327  const std::string& field_name,
328  const boost::optional<std::vector<boost::optional<offset_date_time>>>& value)
329 {
330  if (default_compact_writer != nullptr) {
331  default_compact_writer->write_array_of_timestamp_with_timezone(
332  field_name, value);
333  } else {
334  schema_writer->add_field(
335  field_name, pimpl::field_kind::ARRAY_OF_TIMESTAMP_WITH_TIMEZONE);
336  }
337 }
338 
339 void
340 compact_writer::write_nullable_boolean(const std::string& field_name,
341  const boost::optional<bool>& value)
342 {
343  if (default_compact_writer != nullptr) {
344  default_compact_writer->write_nullable_boolean(field_name, value);
345  } else {
346  schema_writer->add_field(field_name,
347  pimpl::field_kind::NULLABLE_BOOLEAN);
348  }
349 }
350 
351 void
352 compact_writer::write_nullable_int8(const std::string& field_name,
353  const boost::optional<int8_t>& value)
354 {
355  if (default_compact_writer != nullptr) {
356  default_compact_writer->write_nullable_int8(field_name, value);
357  } else {
358  schema_writer->add_field(field_name, pimpl::field_kind::NULLABLE_INT8);
359  }
360 }
361 
362 void
363 compact_writer::write_nullable_int16(const std::string& field_name,
364  const boost::optional<int16_t>& value)
365 {
366  if (default_compact_writer != nullptr) {
367  default_compact_writer->write_nullable_int16(field_name, value);
368  } else {
369  schema_writer->add_field(field_name, pimpl::field_kind::NULLABLE_INT16);
370  }
371 }
372 
373 void
374 compact_writer::write_nullable_int32(const std::string& field_name,
375  const boost::optional<int32_t>& value)
376 {
377  if (default_compact_writer != nullptr) {
378  default_compact_writer->write_nullable_int32(field_name, value);
379  } else {
380  schema_writer->add_field(field_name, pimpl::field_kind::NULLABLE_INT32);
381  }
382 }
383 
384 void
385 compact_writer::write_nullable_int64(const std::string& field_name,
386  const boost::optional<int64_t>& value)
387 {
388  if (default_compact_writer != nullptr) {
389  default_compact_writer->write_nullable_int64(field_name, value);
390  } else {
391  schema_writer->add_field(field_name, pimpl::field_kind::NULLABLE_INT64);
392  }
393 }
394 
395 void
396 compact_writer::write_nullable_float32(const std::string& field_name,
397  const boost::optional<float>& value)
398 {
399  if (default_compact_writer != nullptr) {
400  default_compact_writer->write_nullable_float32(field_name, value);
401  } else {
402  schema_writer->add_field(field_name,
403  pimpl::field_kind::NULLABLE_FLOAT32);
404  }
405 }
406 
407 void
408 compact_writer::write_nullable_float64(const std::string& field_name,
409  const boost::optional<double>& value)
410 {
411  if (default_compact_writer != nullptr) {
412  default_compact_writer->write_nullable_float64(field_name, value);
413  } else {
414  schema_writer->add_field(field_name,
415  pimpl::field_kind::NULLABLE_FLOAT64);
416  }
417 }
418 
419 void
420 compact_writer::write_array_of_nullable_boolean(
421  const std::string& field_name,
422  const boost::optional<std::vector<boost::optional<bool>>>& value)
423 {
424  if (default_compact_writer != nullptr) {
425  default_compact_writer->write_array_of_nullable_boolean(field_name,
426  value);
427  } else {
428  schema_writer->add_field(field_name,
429  pimpl::field_kind::ARRAY_OF_NULLABLE_BOOLEAN);
430  }
431 }
432 
433 void
434 compact_writer::write_array_of_nullable_int8(
435  const std::string& field_name,
436  const boost::optional<std::vector<boost::optional<int8_t>>>& value)
437 {
438  if (default_compact_writer != nullptr) {
439  default_compact_writer->write_array_of_nullable_int8(field_name, value);
440  } else {
441  schema_writer->add_field(field_name,
442  pimpl::field_kind::ARRAY_OF_NULLABLE_INT8);
443  }
444 }
445 
446 void
447 compact_writer::write_array_of_nullable_int16(
448  const std::string& field_name,
449  const boost::optional<std::vector<boost::optional<int16_t>>>& value)
450 {
451  if (default_compact_writer != nullptr) {
452  default_compact_writer->write_array_of_nullable_int16(field_name,
453  value);
454  } else {
455  schema_writer->add_field(field_name,
456  pimpl::field_kind::ARRAY_OF_NULLABLE_INT16);
457  }
458 }
459 
460 void
461 compact_writer::write_array_of_nullable_int32(
462  const std::string& field_name,
463  const boost::optional<std::vector<boost::optional<int32_t>>>& value)
464 {
465  if (default_compact_writer != nullptr) {
466  default_compact_writer->write_array_of_nullable_int32(field_name,
467  value);
468  } else {
469  schema_writer->add_field(field_name,
470  pimpl::field_kind::ARRAY_OF_NULLABLE_INT32);
471  }
472 }
473 
474 void
475 compact_writer::write_array_of_nullable_int64(
476  const std::string& field_name,
477  const boost::optional<std::vector<boost::optional<int64_t>>>& value)
478 {
479  if (default_compact_writer != nullptr) {
480  default_compact_writer->write_array_of_nullable_int64(field_name,
481  value);
482  } else {
483  schema_writer->add_field(field_name,
484  pimpl::field_kind::ARRAY_OF_NULLABLE_INT64);
485  }
486 }
487 
488 void
489 compact_writer::write_array_of_nullable_float32(
490  const std::string& field_name,
491  const boost::optional<std::vector<boost::optional<float>>>& value)
492 {
493  if (default_compact_writer != nullptr) {
494  default_compact_writer->write_array_of_nullable_float32(field_name,
495  value);
496  } else {
497  schema_writer->add_field(field_name,
498  pimpl::field_kind::ARRAY_OF_NULLABLE_FLOAT32);
499  }
500 }
501 
502 void
503 compact_writer::write_array_of_nullable_float64(
504  const std::string& field_name,
505  const boost::optional<std::vector<boost::optional<double>>>& value)
506 {
507  if (default_compact_writer != nullptr) {
508  default_compact_writer->write_array_of_nullable_float64(field_name,
509  value);
510  } else {
511  schema_writer->add_field(field_name,
512  pimpl::field_kind::ARRAY_OF_NULLABLE_FLOAT64);
513  }
514 }
515 
516 namespace pimpl {
517 compact_reader
518 create_compact_reader(
519  pimpl::compact_stream_serializer& compact_stream_serializer,
520  object_data_input& object_data_input,
521  const pimpl::schema& schema)
522 {
523  return compact_reader{ compact_stream_serializer,
524  object_data_input,
525  schema };
526 }
527 } // namespace pimpl
528 
529 const compact_reader::offset_func compact_reader::BYTE_OFFSET_READER =
530  pimpl::offset_reader::get_offset<int8_t>;
531 const compact_reader::offset_func compact_reader::SHORT_OFFSET_READER =
532  pimpl::offset_reader::get_offset<int16_t>;
533 const compact_reader::offset_func compact_reader::INT_OFFSET_READER =
534  pimpl::offset_reader::get_offset<int32_t>;
535 
536 compact_reader::compact_reader(
537  pimpl::compact_stream_serializer& compact_stream_serializer,
538  serialization::object_data_input& object_data_input,
539  const pimpl::schema& schema)
540  : compact_stream_serializer(compact_stream_serializer)
541  , object_data_input(object_data_input)
542  , schema(schema)
543 {
544  size_t final_position;
545  size_t number_of_var_size_fields = schema.number_of_var_size_fields();
546  if (number_of_var_size_fields != 0) {
547  uint32_t data_length = object_data_input.read<int32_t>();
548  data_start_position = object_data_input.position();
549  variable_offsets_position = data_start_position + data_length;
550  if (data_length < pimpl::offset_reader::BYTE_OFFSET_READER_RANGE) {
551  get_offset = BYTE_OFFSET_READER;
552  final_position =
553  variable_offsets_position + number_of_var_size_fields;
554  } else if (data_length <
555  pimpl::offset_reader::SHORT_OFFSET_READER_RANGE) {
556  get_offset = SHORT_OFFSET_READER;
557  final_position =
558  variable_offsets_position +
559  (number_of_var_size_fields * util::Bits::SHORT_SIZE_IN_BYTES);
560  } else {
561  get_offset = INT_OFFSET_READER;
562  final_position =
563  variable_offsets_position +
564  (number_of_var_size_fields * util::Bits::INT_SIZE_IN_BYTES);
565  }
566  } else {
567  get_offset = INT_OFFSET_READER;
568  variable_offsets_position = 0;
569  data_start_position = object_data_input.position();
570  final_position =
571  data_start_position + schema.fixed_size_fields_length();
572  }
573  // set the position to final so that the next one to read something from
574  // `in` can start from correct position
575  object_data_input.position(static_cast<int>(final_position));
576 }
577 
578 bool
579 compact_reader::is_field_exists(const std::string& field_name,
580  enum pimpl::field_kind kind) const
581 {
582  const auto& fields = schema.fields();
583  const auto& field_descriptor = fields.find(field_name);
584  if (field_descriptor == fields.end()) {
585  return false;
586  }
587  return field_descriptor->second.field_kind == kind;
588 }
589 
590 const pimpl::field_descriptor&
591 compact_reader::get_field_descriptor(const std::string& field_name) const
592 {
593  const auto& fields = schema.fields();
594  const auto& field_descriptor = fields.find(field_name);
595  if (field_descriptor == fields.end()) {
596  BOOST_THROW_EXCEPTION(unknown_field(field_name));
597  }
598  return field_descriptor->second;
599 }
600 
601 const pimpl::field_descriptor&
602 compact_reader::get_field_descriptor(const std::string& field_name,
603  enum pimpl::field_kind kind) const
604 {
605  const auto& field_descriptor = get_field_descriptor(field_name);
606  if (field_descriptor.field_kind != kind) {
607  BOOST_THROW_EXCEPTION(
608  unexpected_field_kind(field_descriptor.field_kind, field_name));
609  }
610  return field_descriptor;
611 }
612 
613 std::function<int32_t(serialization::object_data_input&, uint32_t, uint32_t)>
614 compact_reader::get_offset_reader(int32_t data_length)
615 {
616  if (data_length < pimpl::offset_reader::BYTE_OFFSET_READER_RANGE) {
617  return BYTE_OFFSET_READER;
618  } else if (data_length < pimpl::offset_reader::SHORT_OFFSET_READER_RANGE) {
619  return SHORT_OFFSET_READER;
620  } else {
621  return INT_OFFSET_READER;
622  }
623 }
624 
625 exception::hazelcast_serialization
626 compact_reader::unexpected_null_value_in_array(const std::string& field_name,
627  const std::string& method_suffix)
628 {
629  return {
630  "compact_reader",
631  (boost::format(
632  "Error while reading %1%. Array with null items can not be read via "
633  "read_array_of_%2% methods. Use read_array_of_nullable_%2% "
634  "instead") %
635  field_name % method_suffix)
636  .str()
637  };
638 }
639 exception::hazelcast_serialization
640 compact_reader::unknown_field(const std::string& field_name) const
641 {
642  return { "compact_reader",
643  (boost::format("Unknown field name %1% on %2% ") % field_name %
644  schema)
645  .str() };
646 }
647 
648 exception::hazelcast_serialization
649 compact_reader::unexpected_field_kind(enum pimpl::field_kind field_kind,
650  const std::string& field_name) const
651 {
652  return { "compact_reader",
653  (boost::format("Unexpected fieldKind %1% for %2% on %3%") %
654  field_kind % field_name % schema)
655  .str() };
656 }
657 
658 exception::hazelcast_serialization
659 compact_reader::unexpected_null_value(const std::string& field_name,
660  const std::string& method_suffix)
661 {
662  return { "compact_reader",
663  (boost::format(
664  "Error while reading %1%. null value can not be read via "
665  "read_%2% methods. Use read_nullable_%2% instead.") %
666  field_name % method_suffix)
667  .str() };
668 }
669 
670 size_t
671 compact_reader::read_fixed_size_position(
672  const pimpl::field_descriptor& field_descriptor) const
673 {
674  int32_t primitive_offset = field_descriptor.offset;
675  return primitive_offset + data_start_position;
676 }
677 
678 int32_t
679 compact_reader::read_var_size_position(
680  const pimpl::field_descriptor& field_descriptor) const
681 {
682  int32_t index = field_descriptor.index;
683  int32_t offset =
684  get_offset(object_data_input, variable_offsets_position, index);
685  return offset == pimpl::offset_reader::NULL_OFFSET
686  ? pimpl::offset_reader::NULL_OFFSET
687  : offset + data_start_position;
688 }
689 
690 bool
691 compact_reader::read_boolean(const std::string& fieldName)
692 {
693  return read_primitive<bool>(fieldName,
694  pimpl::field_kind::BOOLEAN,
695  pimpl::field_kind::NULLABLE_BOOLEAN,
696  "boolean");
697 }
698 
699 int8_t
700 compact_reader::read_int8(const std::string& fieldName)
701 {
702  return read_primitive<int8_t>(fieldName,
703  pimpl::field_kind::INT8,
704  pimpl::field_kind::NULLABLE_INT8,
705  "int8");
706 }
707 
708 int16_t
709 compact_reader::read_int16(const std::string& field_name)
710 {
711  return read_primitive<int16_t>(field_name,
712  pimpl::field_kind::INT16,
713  pimpl::field_kind::NULLABLE_INT16,
714  "int16");
715 }
716 
717 int32_t
718 compact_reader::read_int32(const std::string& field_name)
719 {
720  return read_primitive<int32_t>(field_name,
721  pimpl::field_kind::INT32,
722  pimpl::field_kind::NULLABLE_INT32,
723  "int32");
724 }
725 
726 int64_t
727 compact_reader::read_int64(const std::string& field_name)
728 {
729  return read_primitive<int64_t>(field_name,
730  pimpl::field_kind::INT64,
731  pimpl::field_kind::NULLABLE_INT64,
732  "int64");
733 }
734 
735 float
736 compact_reader::read_float32(const std::string& field_name)
737 {
738  return read_primitive<float>(field_name,
739  pimpl::field_kind::FLOAT32,
740  pimpl::field_kind::NULLABLE_FLOAT32,
741  "float32");
742 }
743 
744 double
745 compact_reader::read_float64(const std::string& field_name)
746 {
747  return read_primitive<double>(field_name,
748  pimpl::field_kind::FLOAT64,
749  pimpl::field_kind::NULLABLE_FLOAT64,
750  "float64");
751 }
752 
753 boost::optional<std::string>
754 compact_reader::read_string(const std::string& field_name)
755 {
756  return read_variable_size<std::string>(field_name,
757  pimpl::field_kind::STRING);
758 }
759 
760 boost::optional<big_decimal>
761 compact_reader::read_decimal(const std::string& field_name)
762 {
763  return read_variable_size<big_decimal>(field_name,
764  pimpl::field_kind::DECIMAL);
765 }
766 
767 boost::optional<hazelcast::client::local_time>
768 compact_reader::read_time(const std::string& field_name)
769 {
770  return read_variable_size<hazelcast::client::local_time>(
771  field_name, pimpl::field_kind::TIME);
772 }
773 
774 boost::optional<hazelcast::client::local_date>
775 compact_reader::read_date(const std::string& field_name)
776 {
777  return read_variable_size<hazelcast::client::local_date>(
778  field_name, pimpl::field_kind::DATE);
779 }
780 
781 boost::optional<hazelcast::client::local_date_time>
782 compact_reader::read_timestamp(const std::string& field_name)
783 {
784  return read_variable_size<hazelcast::client::local_date_time>(
785  field_name, pimpl::field_kind::TIMESTAMP);
786 }
787 
788 boost::optional<hazelcast::client::offset_date_time>
789 compact_reader::read_timestamp_with_timezone(const std::string& field_name)
790 {
791  return read_variable_size<hazelcast::client::offset_date_time>(
792  field_name, pimpl::field_kind::TIMESTAMP_WITH_TIMEZONE);
793 }
794 
795 boost::optional<std::vector<bool>>
796 compact_reader::read_array_of_boolean(const std::string& field_name)
797 {
798  return read_array_of_primitive<std::vector<bool>>(
799  field_name,
800  pimpl::field_kind::ARRAY_OF_BOOLEAN,
801  pimpl::ARRAY_OF_NULLABLE_BOOLEAN,
802  "boolean");
803 }
804 
805 boost::optional<std::vector<int8_t>>
806 compact_reader::read_array_of_int8(const std::string& field_name)
807 {
808  return read_array_of_primitive<std::vector<int8_t>>(
809  field_name,
810  pimpl::field_kind::ARRAY_OF_INT8,
811  pimpl::ARRAY_OF_NULLABLE_INT8,
812  "int8");
813 }
814 
815 boost::optional<std::vector<int16_t>>
816 compact_reader::read_array_of_int16(const std::string& field_name)
817 {
818  return read_array_of_primitive<std::vector<int16_t>>(
819  field_name,
820  pimpl::field_kind::ARRAY_OF_INT16,
821  pimpl::ARRAY_OF_NULLABLE_INT16,
822  "int16");
823 }
824 
825 boost::optional<std::vector<int32_t>>
826 compact_reader::read_array_of_int32(const std::string& field_name)
827 {
828  return read_array_of_primitive<std::vector<int32_t>>(
829  field_name,
830  pimpl::field_kind::ARRAY_OF_INT32,
831  pimpl::ARRAY_OF_NULLABLE_INT32,
832  "int32");
833 }
834 boost::optional<std::vector<int64_t>>
835 compact_reader::read_array_of_int64(const std::string& field_name)
836 {
837  return read_array_of_primitive<std::vector<int64_t>>(
838  field_name,
839  pimpl::field_kind::ARRAY_OF_INT64,
840  pimpl::ARRAY_OF_NULLABLE_INT64,
841  "int64");
842 }
843 
844 boost::optional<std::vector<float>>
845 compact_reader::read_array_of_float32(const std::string& field_name)
846 {
847  return read_array_of_primitive<std::vector<float>>(
848  field_name,
849  pimpl::field_kind::ARRAY_OF_FLOAT32,
850  pimpl::ARRAY_OF_NULLABLE_FLOAT32,
851  "float32");
852 }
853 
854 boost::optional<std::vector<double>>
855 compact_reader::read_array_of_float64(const std::string& field_name)
856 {
857  return read_array_of_primitive<std::vector<double>>(
858  field_name,
859  pimpl::field_kind::ARRAY_OF_FLOAT64,
860  pimpl::ARRAY_OF_NULLABLE_FLOAT64,
861  "float64");
862 }
863 
864 boost::optional<std::vector<boost::optional<std::string>>>
865 compact_reader::read_array_of_string(const std::string& field_name)
866 {
867  const auto& descriptor =
868  get_field_descriptor(field_name, pimpl::field_kind::ARRAY_OF_STRING);
869  return read_array_of_variable_size<std::string>(descriptor);
870 }
871 
872 boost::optional<std::vector<boost::optional<big_decimal>>>
873 compact_reader::read_array_of_decimal(const std::string& field_name)
874 {
875  const auto& descriptor =
876  get_field_descriptor(field_name, pimpl::field_kind::ARRAY_OF_DECIMAL);
877  return read_array_of_variable_size<big_decimal>(descriptor);
878 }
879 
880 boost::optional<std::vector<boost::optional<local_time>>>
881 compact_reader::read_array_of_time(const std::string& field_name)
882 {
883  const auto& descriptor =
884  get_field_descriptor(field_name, pimpl::field_kind::ARRAY_OF_TIME);
885  return read_array_of_variable_size<local_time>(descriptor);
886 }
887 
888 boost::optional<std::vector<boost::optional<local_date>>>
889 compact_reader::read_array_of_date(const std::string& field_name)
890 {
891  const auto& descriptor =
892  get_field_descriptor(field_name, pimpl::field_kind::ARRAY_OF_DATE);
893  return read_array_of_variable_size<local_date>(descriptor);
894 }
895 
896 boost::optional<std::vector<boost::optional<local_date_time>>>
897 compact_reader::read_array_of_timestamp(const std::string& field_name)
898 {
899  const auto& descriptor =
900  get_field_descriptor(field_name, pimpl::field_kind::ARRAY_OF_TIMESTAMP);
901  return read_array_of_variable_size<local_date_time>(descriptor);
902 }
903 
904 boost::optional<std::vector<boost::optional<offset_date_time>>>
905 compact_reader::read_array_of_timestamp_with_timezone(
906  const std::string& field_name)
907 {
908  const auto& descriptor = get_field_descriptor(
909  field_name, pimpl::field_kind::ARRAY_OF_TIMESTAMP_WITH_TIMEZONE);
910  return read_array_of_variable_size<offset_date_time>(descriptor);
911 }
912 
913 boost::optional<bool>
914 compact_reader::read_nullable_boolean(const std::string& field_name)
915 {
916  return read_nullable_primitive<bool>(field_name,
917  pimpl::field_kind::BOOLEAN,
918  pimpl::field_kind::NULLABLE_BOOLEAN);
919 }
920 
921 boost::optional<int8_t>
922 compact_reader::read_nullable_int8(const std::string& field_name)
923 {
924  return read_nullable_primitive<int8_t>(
925  field_name, pimpl::field_kind::INT8, pimpl::field_kind::NULLABLE_INT8);
926 }
927 
928 boost::optional<int16_t>
929 compact_reader::read_nullable_int16(const std::string& field_name)
930 {
931  return read_nullable_primitive<int16_t>(
932  field_name, pimpl::field_kind::INT16, pimpl::field_kind::NULLABLE_INT16);
933 }
934 
935 boost::optional<int32_t>
936 compact_reader::read_nullable_int32(const std::string& field_name)
937 {
938  return read_nullable_primitive<int32_t>(
939  field_name, pimpl::field_kind::INT32, pimpl::field_kind::NULLABLE_INT32);
940 }
941 
942 boost::optional<int64_t>
943 compact_reader::read_nullable_int64(const std::string& field_name)
944 {
945  return read_nullable_primitive<int64_t>(
946  field_name, pimpl::field_kind::INT64, pimpl::field_kind::NULLABLE_INT64);
947 }
948 
949 boost::optional<float>
950 compact_reader::read_nullable_float32(const std::string& field_name)
951 {
952  return read_nullable_primitive<float>(field_name,
953  pimpl::field_kind::FLOAT32,
954  pimpl::field_kind::NULLABLE_FLOAT32);
955 }
956 
957 boost::optional<double>
958 compact_reader::read_nullable_float64(const std::string& field_name)
959 {
960  return read_nullable_primitive<double>(field_name,
961  pimpl::field_kind::FLOAT64,
962  pimpl::field_kind::NULLABLE_FLOAT64);
963 }
964 
965 boost::optional<std::vector<boost::optional<bool>>>
966 compact_reader::read_array_of_nullable_boolean(const std::string& field_name)
967 {
968  return read_array_of_nullable<bool>(field_name,
969  pimpl::field_kind::ARRAY_OF_BOOLEAN,
970  pimpl::ARRAY_OF_NULLABLE_BOOLEAN);
971 }
972 
973 boost::optional<std::vector<boost::optional<int8_t>>>
974 compact_reader::read_array_of_nullable_int8(const std::string& field_name)
975 {
976  return read_array_of_nullable<int8_t>(field_name,
977  pimpl::field_kind::ARRAY_OF_INT8,
978  pimpl::ARRAY_OF_NULLABLE_INT8);
979 }
980 
981 boost::optional<std::vector<boost::optional<int16_t>>>
982 compact_reader::read_array_of_nullable_int16(const std::string& field_name)
983 {
984  return read_array_of_nullable<int16_t>(field_name,
985  pimpl::field_kind::ARRAY_OF_INT16,
986  pimpl::ARRAY_OF_NULLABLE_INT16);
987 }
988 
989 boost::optional<std::vector<boost::optional<int32_t>>>
990 compact_reader::read_array_of_nullable_int32(const std::string& field_name)
991 {
992  return read_array_of_nullable<int32_t>(field_name,
993  pimpl::field_kind::ARRAY_OF_INT32,
994  pimpl::ARRAY_OF_NULLABLE_INT32);
995 }
996 
997 boost::optional<std::vector<boost::optional<int64_t>>>
998 compact_reader::read_array_of_nullable_int64(const std::string& field_name)
999 {
1000  return read_array_of_nullable<int64_t>(field_name,
1001  pimpl::field_kind::ARRAY_OF_INT64,
1002  pimpl::ARRAY_OF_NULLABLE_INT64);
1003 }
1004 
1005 boost::optional<std::vector<boost::optional<float>>>
1006 compact_reader::read_array_of_nullable_float32(const std::string& field_name)
1007 {
1008  return read_array_of_nullable<float>(field_name,
1009  pimpl::field_kind::ARRAY_OF_FLOAT32,
1010  pimpl::ARRAY_OF_NULLABLE_FLOAT32);
1011 }
1012 
1013 boost::optional<std::vector<boost::optional<double>>>
1014 compact_reader::read_array_of_nullable_float64(const std::string& field_name)
1015 {
1016  return read_array_of_nullable<double>(field_name,
1017  pimpl::field_kind::ARRAY_OF_FLOAT64,
1018  pimpl::ARRAY_OF_NULLABLE_FLOAT64);
1019 }
1020 
1021 namespace pimpl {
1022 
1023 compact_writer
1024 create_compact_writer(pimpl::default_compact_writer* default_compact_writer)
1025 {
1026  return compact_writer{ default_compact_writer };
1027 }
1028 compact_writer
1029 create_compact_writer(pimpl::schema_writer* schema_writer)
1030 {
1031  return compact_writer{ schema_writer };
1032 }
1033 
1034 default_compact_writer::default_compact_writer(
1035  compact_stream_serializer& compact_stream_serializer,
1036  object_data_output& object_data_output,
1037  const schema& schema)
1038  : compact_stream_serializer_(compact_stream_serializer)
1039  , object_data_output_(object_data_output)
1040  , schema_(schema)
1041  , field_offsets(schema.number_of_var_size_fields())
1042 {
1043  if (schema.number_of_var_size_fields() != 0) {
1044  data_start_position =
1045  object_data_output_.position() + util::Bits::INT_SIZE_IN_BYTES;
1046  // Skip for length and primitives.
1047  object_data_output_.write_zero_bytes(schema.fixed_size_fields_length() +
1048  util::Bits::INT_SIZE_IN_BYTES);
1049  } else {
1050  data_start_position = object_data_output_.position();
1051  // Skip for primitives. No need to write data length, when there is no
1052  // variable-size fields.
1053  object_data_output_.write_zero_bytes(schema.fixed_size_fields_length());
1054  }
1055 }
1056 
1057 void
1058 default_compact_writer::write_boolean(const std::string& field_name, bool value)
1059 {
1060  field_descriptor descriptor =
1061  check_field_definition(field_name, field_kind::BOOLEAN);
1062  int32_t offset_in_bytes = descriptor.offset;
1063  int8_t offset_in_bits = descriptor.bit_offset;
1064  size_t write_offset = offset_in_bytes + data_start_position;
1065  object_data_output_.write_boolean_bit_at(
1066  write_offset, offset_in_bits, value);
1067 }
1068 
1069 void
1070 default_compact_writer::write_int8(const std::string& field_name, int8_t value)
1071 {
1072  size_t position =
1073  get_fixed_size_field_position(field_name, field_kind::INT8);
1074  object_data_output_.write_at(position, value);
1075 }
1076 
1077 void
1078 default_compact_writer::write_int16(const std::string& field_name,
1079  int16_t value)
1080 {
1081  size_t position =
1082  get_fixed_size_field_position(field_name, field_kind::INT16);
1083  object_data_output_.write_at(position, value);
1084 }
1085 
1086 void
1087 default_compact_writer::write_int32(const std::string& field_name,
1088  int32_t value)
1089 {
1090  size_t position =
1091  get_fixed_size_field_position(field_name, field_kind::INT32);
1092  object_data_output_.write_at(position, value);
1093 }
1094 
1095 void
1096 default_compact_writer::write_int64(const std::string& field_name,
1097  int64_t value)
1098 {
1099  size_t position =
1100  get_fixed_size_field_position(field_name, field_kind::INT64);
1101  object_data_output_.write_at(position, value);
1102 }
1103 
1104 void
1105 default_compact_writer::write_float32(const std::string& field_name,
1106  float value)
1107 {
1108  size_t position =
1109  get_fixed_size_field_position(field_name, field_kind::FLOAT32);
1110  object_data_output_.write_at(position, value);
1111 }
1112 
1113 void
1114 default_compact_writer::write_float64(const std::string& field_name,
1115  double value)
1116 {
1117  size_t position =
1118  get_fixed_size_field_position(field_name, field_kind::FLOAT64);
1119  object_data_output_.write_at(position, value);
1120 }
1121 
1122 void
1123 default_compact_writer::write_string(const std::string& field_name,
1124  const boost::optional<std::string>& value)
1125 {
1126  write_variable_size_field(field_name, field_kind::STRING, value);
1127 }
1128 
1129 void
1130 default_compact_writer::write_decimal(const std::string& field_name,
1131  const boost::optional<big_decimal>& value)
1132 {
1133  write_variable_size_field(field_name, field_kind::DECIMAL, value);
1134 }
1135 
1136 void
1137 default_compact_writer::write_time(
1138  const std::string& field_name,
1139  const boost::optional<hazelcast::client::local_time>& value)
1140 {
1141  write_variable_size_field(field_name, field_kind::TIME, value);
1142 }
1143 void
1144 default_compact_writer::write_date(
1145  const std::string& field_name,
1146  const boost::optional<hazelcast::client::local_date>& value)
1147 {
1148  write_variable_size_field(field_name, field_kind::DATE, value);
1149 }
1150 
1151 void
1152 default_compact_writer::write_timestamp(
1153  const std::string& field_name,
1154  const boost::optional<hazelcast::client::local_date_time>& value)
1155 {
1156  write_variable_size_field(field_name, field_kind::TIMESTAMP, value);
1157 }
1158 
1159 void
1160 default_compact_writer::write_timestamp_with_timezone(
1161  const std::string& field_name,
1162  const boost::optional<hazelcast::client::offset_date_time>& value)
1163 {
1164  write_variable_size_field(
1165  field_name, field_kind::TIMESTAMP_WITH_TIMEZONE, value);
1166 }
1167 
1168 void
1169 default_compact_writer::write_array_of_boolean(
1170  const std::string& field_name,
1171  const boost::optional<std::vector<bool>>& value)
1172 {
1173  write_variable_size_field(field_name, field_kind::ARRAY_OF_BOOLEAN, value);
1174 }
1175 
1176 void
1177 default_compact_writer::write_array_of_int8(
1178  const std::string& field_name,
1179  const boost::optional<std::vector<int8_t>>& value)
1180 {
1181  write_variable_size_field(field_name, field_kind::ARRAY_OF_INT8, value);
1182 }
1183 
1184 void
1185 default_compact_writer::write_array_of_int16(
1186  const std::string& field_name,
1187  const boost::optional<std::vector<int16_t>>& value)
1188 {
1189  write_variable_size_field(field_name, field_kind::ARRAY_OF_INT16, value);
1190 }
1191 
1192 void
1193 default_compact_writer::write_array_of_int32(
1194  const std::string& field_name,
1195  const boost::optional<std::vector<int32_t>>& value)
1196 {
1197  write_variable_size_field(field_name, field_kind::ARRAY_OF_INT32, value);
1198 }
1199 
1200 void
1201 default_compact_writer::write_array_of_int64(
1202  const std::string& field_name,
1203  const boost::optional<std::vector<int64_t>>& value)
1204 {
1205  write_variable_size_field(field_name, field_kind::ARRAY_OF_INT64, value);
1206 }
1207 
1208 void
1209 default_compact_writer::write_array_of_float32(
1210  const std::string& field_name,
1211  const boost::optional<std::vector<float>>& value)
1212 {
1213  write_variable_size_field(field_name, field_kind::ARRAY_OF_FLOAT32, value);
1214 }
1215 
1216 void
1217 default_compact_writer::write_array_of_float64(
1218  const std::string& field_name,
1219  const boost::optional<std::vector<double>>& value)
1220 {
1221  write_variable_size_field(field_name, field_kind::ARRAY_OF_FLOAT64, value);
1222 }
1223 
1224 void
1225 default_compact_writer::write_array_of_string(
1226  const std::string& field_name,
1227  const boost::optional<std::vector<boost::optional<std::string>>>& value)
1228 {
1229  write_array_of_variable_size(
1230  field_name, field_kind::ARRAY_OF_STRING, value);
1231 }
1232 
1233 void
1234 default_compact_writer::write_array_of_decimal(
1235  const std::string& field_name,
1236  const boost::optional<std::vector<boost::optional<big_decimal>>>& value)
1237 {
1238  write_array_of_variable_size(
1239  field_name, field_kind::ARRAY_OF_DECIMAL, value);
1240 }
1241 
1242 void
1243 default_compact_writer::write_array_of_time(
1244  const std::string& field_name,
1245  const boost::optional<std::vector<boost::optional<local_time>>>& value)
1246 {
1247  write_array_of_variable_size(field_name, field_kind::ARRAY_OF_TIME, value);
1248 }
1249 
1250 void
1251 default_compact_writer::write_array_of_date(
1252  const std::string& field_name,
1253  const boost::optional<std::vector<boost::optional<local_date>>>& value)
1254 {
1255  write_array_of_variable_size(field_name, field_kind::ARRAY_OF_DATE, value);
1256 }
1257 
1258 void
1259 default_compact_writer::write_array_of_timestamp(
1260  const std::string& field_name,
1261  const boost::optional<std::vector<boost::optional<local_date_time>>>& value)
1262 {
1263  write_array_of_variable_size(
1264  field_name, field_kind::ARRAY_OF_TIMESTAMP, value);
1265 }
1266 
1267 void
1268 default_compact_writer::write_array_of_timestamp_with_timezone(
1269  const std::string& field_name,
1270  const boost::optional<std::vector<boost::optional<offset_date_time>>>& value)
1271 {
1272  write_array_of_variable_size(
1273  field_name, field_kind::ARRAY_OF_TIMESTAMP_WITH_TIMEZONE, value);
1274 }
1275 
1276 void
1277 default_compact_writer::write_nullable_boolean(
1278  const std::string& field_name,
1279  const boost::optional<bool>& value)
1280 {
1281  write_variable_size_field(field_name, field_kind::NULLABLE_BOOLEAN, value);
1282 }
1283 void
1284 default_compact_writer::write_nullable_int8(
1285  const std::string& field_name,
1286  const boost::optional<int8_t>& value)
1287 {
1288  write_variable_size_field(field_name, field_kind::NULLABLE_INT8, value);
1289 }
1290 void
1291 default_compact_writer::write_nullable_int16(
1292  const std::string& field_name,
1293  const boost::optional<int16_t>& value)
1294 {
1295  write_variable_size_field(field_name, field_kind::NULLABLE_INT16, value);
1296 }
1297 void
1298 default_compact_writer::write_nullable_int32(
1299  const std::string& field_name,
1300  const boost::optional<int32_t>& value)
1301 {
1302  write_variable_size_field(field_name, field_kind::NULLABLE_INT32, value);
1303 }
1304 void
1305 default_compact_writer::write_nullable_int64(
1306  const std::string& field_name,
1307  const boost::optional<int64_t>& value)
1308 {
1309  write_variable_size_field(field_name, field_kind::NULLABLE_INT64, value);
1310 }
1311 void
1312 default_compact_writer::write_nullable_float32(
1313  const std::string& field_name,
1314  const boost::optional<float>& value)
1315 {
1316  write_variable_size_field(field_name, field_kind::NULLABLE_FLOAT32, value);
1317 }
1318 void
1319 default_compact_writer::write_nullable_float64(
1320  const std::string& field_name,
1321  const boost::optional<double>& value)
1322 {
1323  write_variable_size_field(field_name, field_kind::NULLABLE_FLOAT64, value);
1324 }
1325 
1326 void
1327 default_compact_writer::write_array_of_nullable_boolean(
1328  const std::string& field_name,
1329  const boost::optional<std::vector<boost::optional<bool>>>& value)
1330 {
1331  write_array_of_variable_size(
1332  field_name, field_kind::ARRAY_OF_NULLABLE_BOOLEAN, value);
1333 }
1334 
1335 void
1336 default_compact_writer::write_array_of_nullable_int8(
1337  const std::string& field_name,
1338  const boost::optional<std::vector<boost::optional<int8_t>>>& value)
1339 {
1340  write_array_of_variable_size(
1341  field_name, field_kind::ARRAY_OF_NULLABLE_INT8, value);
1342 }
1343 
1344 void
1345 default_compact_writer::write_array_of_nullable_int16(
1346  const std::string& field_name,
1347  const boost::optional<std::vector<boost::optional<int16_t>>>& value)
1348 {
1349  write_array_of_variable_size(
1350  field_name, field_kind::ARRAY_OF_NULLABLE_INT16, value);
1351 }
1352 
1353 void
1354 default_compact_writer::write_array_of_nullable_int32(
1355  const std::string& field_name,
1356  const boost::optional<std::vector<boost::optional<int32_t>>>& value)
1357 {
1358  write_array_of_variable_size(
1359  field_name, field_kind::ARRAY_OF_NULLABLE_INT32, value);
1360 }
1361 
1362 void
1363 default_compact_writer::write_array_of_nullable_int64(
1364  const std::string& field_name,
1365  const boost::optional<std::vector<boost::optional<int64_t>>>& value)
1366 {
1367  write_array_of_variable_size(
1368  field_name, field_kind::ARRAY_OF_NULLABLE_INT64, value);
1369 }
1370 
1371 void
1372 default_compact_writer::write_array_of_nullable_float32(
1373  const std::string& field_name,
1374  const boost::optional<std::vector<boost::optional<float>>>& value)
1375 {
1376  write_array_of_variable_size(
1377  field_name, field_kind::ARRAY_OF_NULLABLE_FLOAT32, value);
1378 }
1379 
1380 void
1381 default_compact_writer::write_array_of_nullable_float64(
1382  const std::string& field_name,
1383  const boost::optional<std::vector<boost::optional<double>>>& value)
1384 {
1385  write_array_of_variable_size(
1386  field_name, field_kind::ARRAY_OF_NULLABLE_FLOAT64, value);
1387 }
1388 
1389 void
1390 default_compact_writer::end()
1391 {
1392  if (schema_.number_of_var_size_fields() == 0) {
1393  // There are no variable size fields
1394  return;
1395  }
1396  size_t position = object_data_output_.position();
1397  size_t data_length = position - data_start_position;
1398  write_offsets(data_length, field_offsets);
1399  // write dataLength
1400  object_data_output_.write_at(data_start_position -
1401  util::Bits::INT_SIZE_IN_BYTES,
1402  (int32_t)data_length);
1403 }
1404 
1405 size_t
1406 default_compact_writer::get_fixed_size_field_position(
1407  const std::string& field_name,
1408  enum field_kind field_kind) const
1409 {
1410  const field_descriptor& field_descriptor =
1411  check_field_definition(field_name, field_kind);
1412  return field_descriptor.offset + data_start_position;
1413 }
1414 
1415 const field_descriptor&
1416 default_compact_writer::check_field_definition(const std::string& field_name,
1417  enum field_kind field_kind) const
1418 {
1419  auto iterator = schema_.fields().find(field_name);
1420  if (iterator == schema_.fields().end()) {
1421  BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
1422  "default_compact_writer",
1423  (boost::format("Invalid field name %1% for %2%") % field_name %
1424  schema_)
1425  .str()));
1426  }
1427  if (iterator->second.field_kind != field_kind) {
1428  BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
1429  "default_compact_writer",
1430  (boost::format("Invalid field type %1% for %2%") % field_name %
1431  schema_)
1432  .str()));
1433  }
1434  return iterator->second;
1435 }
1436 
1437 void
1438 default_compact_writer::write_offsets(size_t data_length,
1439  const std::vector<int32_t>& offsets)
1440 {
1441  if (data_length < offset_reader::BYTE_OFFSET_READER_RANGE) {
1442  for (int32_t offset : offsets) {
1443  object_data_output_.write<int8_t>(static_cast<int8_t>(offset));
1444  }
1445  } else if (data_length < offset_reader::SHORT_OFFSET_READER_RANGE) {
1446  for (int32_t offset : offsets) {
1447  object_data_output_.write<int16_t>(static_cast<int16_t>(offset));
1448  }
1449  } else {
1450  for (int32_t offset : offsets) {
1451  object_data_output_.write<int32_t>(offset);
1452  }
1453  }
1454 }
1455 
1456 void
1457 default_compact_writer::set_position(const std::string& field_name,
1458  enum field_kind field_kind)
1459 {
1460  const auto& field_descriptor =
1461  check_field_definition(field_name, field_kind);
1462  size_t pos = object_data_output_.position();
1463  size_t fieldPosition = pos - data_start_position;
1464  int index = field_descriptor.index;
1465  field_offsets[index] = static_cast<int32_t>(fieldPosition);
1466 }
1467 
1468 void
1469 default_compact_writer::set_position_as_null(const std::string& field_name,
1470  enum field_kind field_kind)
1471 {
1472  const auto& field_descriptor =
1473  check_field_definition(field_name, field_kind);
1474  int index = field_descriptor.index;
1475  field_offsets[index] = -1;
1476 }
1477 
1478 namespace rabin_finger_print {
1483 constexpr uint64_t INIT = 0xc15d213aa4d7a795L;
1484 
1485 static std::array<uint64_t, 256>
1486 init_fp_table()
1487 {
1488  static std::array<uint64_t, 256> FP_TABLE;
1489  for (int i = 0; i < 256; ++i) {
1490  uint64_t fp = i;
1491  for (int j = 0; j < 8; ++j) {
1492  fp = (fp >> 1) ^ (INIT & -(fp & 1L));
1493  }
1494  FP_TABLE[i] = fp;
1495  }
1496  return FP_TABLE;
1497 }
1498 uint64_t
1499 FP_TABLE_AT(int index)
1500 {
1501  static auto FP_TABLE = init_fp_table();
1502  return FP_TABLE[index];
1503 }
1504 
1505 uint64_t
1506 fingerprint64(uint64_t fp, byte b)
1507 {
1508  return (fp >> 8) ^ FP_TABLE_AT((int)(fp ^ b) & 0xff);
1509 }
1510 
1511 uint64_t
1512 fingerprint64(uint64_t fp, int v)
1513 {
1514  fp = fingerprint64(fp, (byte)((v)&0xFF));
1515  fp = fingerprint64(fp, (byte)((v >> 8) & 0xFF));
1516  fp = fingerprint64(fp, (byte)((v >> 16) & 0xFF));
1517  fp = fingerprint64(fp, (byte)((v >> 24) & 0xFF));
1518  return fp;
1519 }
1520 
1521 uint64_t
1522 fingerprint64(uint64_t fp, const std::string& value)
1523 {
1524  fp = fingerprint64(fp, (int)value.size());
1525  for (const auto& item : value) {
1526  fp = fingerprint64(fp, (byte)item);
1527  }
1528  return fp;
1529 }
1530 
1534 int64_t
1535 fingerprint64(const std::string& type_name,
1536  std::map<std::string, field_descriptor>& fields)
1537 {
1538  uint64_t fingerPrint = fingerprint64(INIT, type_name);
1539  fingerPrint = fingerprint64(fingerPrint, (int)fields.size());
1540  for (const auto& entry : fields) {
1541  const field_descriptor& descriptor = entry.second;
1542  fingerPrint = fingerprint64(fingerPrint, entry.first);
1543  fingerPrint = fingerprint64(fingerPrint, (int)descriptor.field_kind);
1544  }
1545  return static_cast<int64_t>(fingerPrint);
1546 }
1547 
1548 } // namespace rabin_finger_print
1549 
1550 bool
1551 kind_size_comparator(const field_descriptor* i, const field_descriptor* j)
1552 {
1553  auto i_kind_size =
1554  field_operations::get(i->field_kind).kind_size_in_byte_func();
1555  auto j_kind_size =
1556  field_operations::get(j->field_kind).kind_size_in_byte_func();
1557  return i_kind_size > j_kind_size;
1558 }
1559 
1560 schema::schema(
1561  std::string type_name,
1562  std::unordered_map<std::string, field_descriptor>&& field_definition_map)
1563  : type_name_(std::move(type_name))
1564  , field_definition_map_(std::move(field_definition_map))
1565 {
1566  std::vector<field_descriptor*> fixed_size_fields;
1567  std::vector<field_descriptor*> boolean_fields;
1568  std::vector<field_descriptor*> variable_size_fields;
1569 
1570  std::map<std::string, field_descriptor> sorted_fields(
1571  field_definition_map_.begin(), field_definition_map_.end());
1572  for (auto& item : sorted_fields) {
1573  field_descriptor& descriptor = item.second;
1574  field_kind kind = descriptor.field_kind;
1575  if (field_operations::get(kind).kind_size_in_byte_func() ==
1576  field_kind_based_operations::VARIABLE_SIZE) {
1577  variable_size_fields.push_back(&descriptor);
1578  } else if (kind == field_kind::BOOLEAN) {
1579  boolean_fields.push_back(&descriptor);
1580  } else {
1581  fixed_size_fields.push_back(&descriptor);
1582  }
1583  }
1584 
1585  std::sort(
1586  fixed_size_fields.begin(), fixed_size_fields.end(), kind_size_comparator);
1587 
1588  int offset = 0;
1589  for (auto descriptor : fixed_size_fields) {
1590  descriptor->offset = offset;
1591  offset += field_operations::get(descriptor->field_kind)
1592  .kind_size_in_byte_func();
1593  }
1594 
1595  int8_t bit_offset = 0;
1596  for (auto descriptor : boolean_fields) {
1597  descriptor->offset = offset;
1598  descriptor->bit_offset =
1599  static_cast<int8_t>(bit_offset % util::Bits::BITS_IN_BYTE);
1600  bit_offset++;
1601  if (bit_offset % util::Bits::BITS_IN_BYTE == 0) {
1602  offset += 1;
1603  }
1604  }
1605  if (bit_offset % util::Bits::BITS_IN_BYTE != 0) {
1606  offset += 1;
1607  }
1608 
1609  fixed_size_fields_length_ = offset;
1610 
1611  int index = 0;
1612  for (auto descriptor : variable_size_fields) {
1613  descriptor->index = index;
1614  index++;
1615  }
1616 
1617  for (auto& item : sorted_fields) {
1618  field_definition_map_[item.first] = item.second;
1619  }
1620 
1621  number_of_var_size_fields_ = index;
1622  schema_id_ = rabin_finger_print::fingerprint64(type_name_, sorted_fields);
1623 }
1624 
1625 int64_t
1626 schema::schema_id() const
1627 {
1628  return schema_id_;
1629 }
1630 
1631 size_t
1632 schema::number_of_var_size_fields() const
1633 {
1634  return number_of_var_size_fields_;
1635 }
1636 
1637 size_t
1638 schema::fixed_size_fields_length() const
1639 {
1640  return fixed_size_fields_length_;
1641 }
1642 
1643 const std::string&
1644 schema::type_name() const
1645 {
1646  return type_name_;
1647 }
1648 
1649 const std::unordered_map<std::string, field_descriptor>&
1650 schema::fields() const
1651 {
1652  return field_definition_map_;
1653 }
1654 
1655 std::ostream&
1656 operator<<(std::ostream& os, const schema& schema)
1657 {
1658  os << "type name " << schema.type_name() << ",number of var size fields "
1659  << schema.number_of_var_size_fields() << ",fixed size fields length "
1660  << schema.fixed_size_fields_length() << ",fields {";
1661  for (const auto& item : schema.fields()) {
1662  os << item.first << " " << item.second << ",";
1663  }
1664  os << "}";
1665  return os;
1666 }
1667 
1668 std::ostream&
1669 operator<<(std::ostream& os, const field_descriptor& field_descriptor)
1670 {
1671  os << field_descriptor.field_kind;
1672  return os;
1673 }
1674 
1675 } // namespace pimpl
1676 
1677 namespace pimpl {
1678 schema_writer::schema_writer(std::string type_name)
1679  : type_name(std::move(type_name))
1680 {}
1681 void
1682 schema_writer::add_field(std::string field_name, enum field_kind kind)
1683 {
1684  field_definition_map[std::move(field_name)] =
1685  field_descriptor{ kind, -1, -1, -1 };
1686 }
1687 
1688 schema
1689 schema_writer::build() &&
1690 {
1691  return schema{ type_name, std::move(field_definition_map) };
1692 }
1693 
1694 schema
1695 default_schema_service::get(int64_t schemaId)
1696 {
1697  auto ptr = schemas.get(schemaId);
1698  if (ptr == nullptr) {
1699  // TODO sancar throw schema_does_not_exist;
1700  }
1701  return *ptr;
1702 }
1703 void
1704 default_schema_service::put(const schema& schema_v)
1705 {
1706  if (schemas.contains_key(schema_v.schema_id())) {
1707  return;
1708  }
1709  schemas.put(schema_v.schema_id(), std::make_shared<schema>(schema_v));
1710 }
1711 
1712 void
1713 compact_stream_serializer::put_to_schema_service(const schema& schema)
1714 {
1715  schema_service.put(schema);
1716 }
1717 
1718 field_kind_based_operations::field_kind_based_operations()
1719  : kind_size_in_byte_func(DEFAULT_KIND_SIZE_IN_BYTES)
1720 {}
1721 
1722 field_kind_based_operations::field_kind_based_operations(
1723  std::function<int()> kind_size_in_byte_func)
1724  : kind_size_in_byte_func(std::move(kind_size_in_byte_func))
1725 {}
1726 field_kind_based_operations
1727 field_operations::get(enum field_kind field_kind)
1728 {
1729  static const field_kind_based_operations ALL[NUMBER_OF_FIELD_KINDS] = {
1730  field_kind_based_operations{ []() { return 0; } },
1731  field_kind_based_operations{},
1732  field_kind_based_operations{ []() { return 1; } },
1733  field_kind_based_operations{},
1734  field_kind_based_operations{},
1735  field_kind_based_operations{},
1736  field_kind_based_operations{
1737  []() { return util::Bits::SHORT_SIZE_IN_BYTES; } },
1738  field_kind_based_operations{},
1739  field_kind_based_operations(
1740  []() { return util::Bits::INT_SIZE_IN_BYTES; }),
1741  field_kind_based_operations{},
1742  field_kind_based_operations{
1743  []() { return util::Bits::LONG_SIZE_IN_BYTES; } },
1744  field_kind_based_operations{},
1745  field_kind_based_operations{
1746  []() { return util::Bits::FLOAT_SIZE_IN_BYTES; } },
1747  field_kind_based_operations{},
1748  field_kind_based_operations{
1749  []() { return util::Bits::DOUBLE_SIZE_IN_BYTES; } },
1750  field_kind_based_operations{},
1751  field_kind_based_operations{},
1752  field_kind_based_operations{},
1753  field_kind_based_operations{},
1754  field_kind_based_operations{},
1755  field_kind_based_operations{},
1756  field_kind_based_operations{},
1757  field_kind_based_operations{},
1758  field_kind_based_operations{},
1759  field_kind_based_operations{},
1760  field_kind_based_operations{},
1761  field_kind_based_operations{},
1762  field_kind_based_operations{},
1763  field_kind_based_operations{},
1764  field_kind_based_operations{},
1765  field_kind_based_operations{},
1766  field_kind_based_operations{},
1767  field_kind_based_operations{},
1768  field_kind_based_operations{},
1769  field_kind_based_operations{},
1770  field_kind_based_operations{},
1771  field_kind_based_operations{},
1772  field_kind_based_operations{},
1773  field_kind_based_operations{},
1774  field_kind_based_operations{},
1775  field_kind_based_operations{},
1776  field_kind_based_operations{},
1777  field_kind_based_operations{},
1778  field_kind_based_operations{},
1779  field_kind_based_operations{},
1780  field_kind_based_operations{}
1781  };
1782  return ALL[field_kind];
1783 }
1784 } // namespace pimpl
1785 } // namespace serialization
1786 } // namespace client
1787 } // namespace hazelcast