RTC Toolkit 6.0.0-pre2
Loading...
Searching...
No Matches
repositoryIf.ipp
Go to the documentation of this file.
1
12
13// Note this is a template implementation file and should not be included directly.
14// The typical header protection macro is not added to avoid it showing up in Doxygen API
15// documentation.
16#pragma once
17
19
20#include <fmt/format.h>
21
22#include <boost/container/vector.hpp>
23#include <boost/core/demangle.hpp>
24
25#include <cassert>
26#include <exception>
27#include <memory>
28#include <unordered_set>
29#include <utility>
30
32
33// NOLINTBEGIN(readability-identifier-naming)
35// NOLINTEND(readability-identifier-naming)
36
37namespace detail {
38
39template <typename T>
47
52
58
61 bool recurse;
62 std::pair<RepositoryIf::PathList, RepositoryIf::PathList>& result;
64};
65
66template <typename T>
68 using ElementType = T;
69 using PrepareFunctionType = std::function<gsl::span<T>(const RepositoryIf::MetaData&)>;
71 // The following function is given by the caller to prepare the buffer to be filled.
72 // It can use the metadata available for the datapoint to resize the buffer object for
73 // example. This is called by the adapter just before filling the returned span with
74 // deserialised data.
76 std::optional<std::reference_wrapper<RepositoryIf::MetaData>> metadata;
78};
79
80template <typename T>
82 using ElementType = T;
84 gsl::span<const T> data;
86 std::optional<std::reference_wrapper<RepositoryIf::MetaData>> output_metadata;
88};
89
90template <typename T>
92 using ElementType = T;
94 gsl::span<T> data;
96 std::optional<std::reference_wrapper<RepositoryIf::MetaData>> output_metadata;
97 size_t offset;
99};
100
101template <typename T>
103 using ElementType = T;
105 gsl::span<const T> data;
107 size_t offset;
108 std::optional<std::reference_wrapper<RepositoryIf::MetaData>> output_metadata;
110};
111
117
123
129
135
137 RtcUInt64 nelements = 1;
138 for (auto dimention : shape) {
139 nelements *= dimention;
140 }
141 return nelements;
142}
143
144inline void EnsureAbsolutePath(const DataPointPath& path) {
145 if (not path.IsAbsolutePath()) {
146 throw CII_MAKE_EXCEPTION(RepositoryIf::DataPointPathNotAbsolute,
147 fmt::format("DataPointPath is not absolute: '{}'.", path));
148 }
149}
150
151template <typename T>
154 using BufferType = T;
155
157 using ElementType = std::remove_cv_t<T>;
158
160 using DataPointType = T;
161
163 static const bool USES_TEMP_BUFFER = false;
164
166 using TempBufferType = void;
167
175 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
176 static_assert(
177 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
178 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
179 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
180 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
181 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
182 std::is_same_v<ElementType, RtcDouble>,
183 "The scalar type is not supported.");
184 return {};
185 }
186
192 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
193 return {&buffer, 1};
194 }
195
201 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
202 return {&buffer, 1};
203 }
204
218 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
219 if (shape.size() == 0) {
220 // The shape is for a scalar, so confirm the buffer size is correct.
221 return true;
222 } else {
223 return false;
224 }
225 }
226
240 static void CopyToTempBuffer(const BufferType& buffer,
241 std::shared_ptr<TempBufferType>& temp_buffer,
242 size_t offset,
243 size_t count) = delete;
244
258 static void CopyFromTempBuffer(BufferType& buffer,
259 const std::shared_ptr<TempBufferType>& temp_buffer,
260 size_t offset,
261 size_t count) = delete;
262};
263
264template <>
265struct UserTypeHandler<std::string> {
266 using BufferType = std::string;
267 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
269 static const bool USES_TEMP_BUFFER = false;
270 using TempBufferType = void;
271
272 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
273 return {buffer.size()};
274 }
275
276 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
277 return {buffer};
278 }
279
280 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
281 return {buffer};
282 }
283
284 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
285 if (shape.size() == 1) {
286 buffer.resize(shape[0]);
287 } else {
288 buffer.resize(GetNumOfElements(shape));
289 }
290 return true;
291 }
292};
293
294template <>
295struct UserTypeHandler<std::string_view> {
296 using BufferType = std::string_view;
297 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
299 static const bool USES_TEMP_BUFFER = false;
300 using TempBufferType = void;
301
302 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
303 return {buffer.size()};
304 }
305
309 static gsl::span<ElementType> MakeSpan(BufferType& buffer) = delete;
310
311 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
312 return {buffer.data(), buffer.size()};
313 }
314
315 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
316 if (shape.size() == 1 and shape[0] == buffer.size()) {
317 // Cannot resize, but the shape and size is correct, so return true.
318 return true;
319 } else {
320 return false;
321 }
322 }
323};
324
325template <typename T, typename A>
326struct UserTypeHandler<std::vector<T, A>> {
327 using BufferType = std::vector<T, A>;
328 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
330 static const bool USES_TEMP_BUFFER = false;
331 using TempBufferType = void;
332
333 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
334 static_assert(
335 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
336 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
337 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
338 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
339 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
340 std::is_same_v<ElementType, RtcDouble> or std::is_same_v<ElementType, RtcString> or
341 std::is_same_v<ElementType, std::byte>,
342 "The vector type is not supported.");
343 return {buffer.size()};
344 }
345
346 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
347 return {buffer};
348 }
349
350 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
351 return {buffer};
352 }
353
354 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
355 if (shape.size() == 1) {
356 buffer.resize(shape[0]);
357 } else {
358 buffer.resize(GetNumOfElements(shape));
359 }
360 return true;
361 }
362};
363
364template <typename A>
365struct UserTypeHandler<std::vector<bool, A>> {
366 using BufferType = std::vector<bool, A>;
367 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
369 static const bool USES_TEMP_BUFFER = true;
370 using TempBufferType = boost::container::vector<bool>;
371
372 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
373 return {buffer.size()};
374 }
375
379 static gsl::span<ElementType> MakeSpan(BufferType& buffer) = delete;
380
384 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) = delete;
385
386 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
387 if (shape.size() == 1) {
388 buffer.resize(shape[0]);
389 } else {
390 buffer.resize(GetNumOfElements(shape));
391 }
392 return true;
393 }
394
395 static void CopyToTempBuffer(const BufferType& buffer,
396 std::shared_ptr<TempBufferType>& temp_buffer,
397 size_t offset,
398 size_t count) {
399 assert((buffer.size() >= offset + count) && ("The input buffer is too small."));
400 assert((temp_buffer->size() >= count) && ("The temporary buffer is too small."));
401 std::copy(buffer.begin() + offset, buffer.begin() + offset + count, temp_buffer->begin());
402 }
403
404 static void CopyFromTempBuffer(BufferType& buffer,
405 const std::shared_ptr<TempBufferType>& temp_buffer,
406 size_t offset,
407 size_t count) {
408 assert((buffer.size() >= offset + count) && ("The output buffer is too small."));
409 assert((temp_buffer->size() >= count) && ("The temporary buffer is too small."));
410 std::copy(temp_buffer->begin(), temp_buffer->begin() + count, buffer.begin() + offset);
411 }
412};
413
414template <typename T, typename A>
415struct UserTypeHandler<boost::container::vector<T, A>> {
416 using BufferType = boost::container::vector<T, A>;
417 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
419 static const bool USES_TEMP_BUFFER = false;
420 using TempBufferType = void;
421
422 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
423 static_assert(
424 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
425 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
426 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
427 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
428 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
429 std::is_same_v<ElementType, RtcDouble> or std::is_same_v<ElementType, RtcString> or
430 std::is_same_v<ElementType, std::byte>,
431 "The vector type is not supported.");
432 return {buffer.size()};
433 }
434
435 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
436 return {buffer};
437 }
438
439 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
440 return {buffer};
441 }
442
443 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
444 if (shape.size() == 1) {
445 buffer.resize(shape[0]);
446 } else {
447 buffer.resize(GetNumOfElements(shape));
448 }
449 return true;
450 }
451};
452
453template <typename T, decltype(gsl::dynamic_extent) N>
454struct UserTypeHandler<gsl::span<T, N>> {
455 using BufferType = gsl::span<T, N>;
456 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
458 static const bool USES_TEMP_BUFFER = false;
459 using TempBufferType = void;
460
461 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
462 static_assert(
463 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
464 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
465 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
466 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
467 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
468 std::is_same_v<ElementType, RtcDouble> or std::is_same_v<ElementType, RtcString> or
469 std::is_same_v<ElementType, std::byte>,
470 "The vector type is not supported.");
471 return {buffer.size()};
472 }
473
474 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
475 return {buffer};
476 }
477
478 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
479 return {buffer};
480 }
481
482 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
483 if (shape.size() == 1 and shape[0] == buffer.size()) {
484 // Cannot resize, but the shape and size is correct, so return true.
485 return true;
486 } else {
487 return false;
488 }
489 }
490};
491
492template <decltype(gsl::dynamic_extent) N>
493struct UserTypeHandler<gsl::span<char, N>> {
494 using BufferType = gsl::span<char, N>;
495 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
497 static const bool USES_TEMP_BUFFER = false;
498 using TempBufferType = void;
499
500 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
501 return {buffer.size()};
502 }
503
504 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
505 return {buffer};
506 }
507
508 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
509 return {buffer};
510 }
511
512 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
513 return false;
514 }
515};
516
517template <decltype(gsl::dynamic_extent) N>
518struct UserTypeHandler<gsl::span<const char, N>> {
519 using BufferType = gsl::span<const char, N>;
520 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
522 static const bool USES_TEMP_BUFFER = false;
523 using TempBufferType = void;
524
525 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
526 return {buffer.size()};
527 }
528
529 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
530 return {buffer};
531 }
532
533 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
534 return {buffer};
535 }
536
537 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
538 return false;
539 }
540};
541
542template <typename T, typename A>
545 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
547 static const bool USES_TEMP_BUFFER = false;
548 using TempBufferType = void;
549
550 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
551 static_assert(
552 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
553 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
554 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
555 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
556 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
557 std::is_same_v<ElementType, RtcDouble> or std::is_same_v<ElementType, RtcString>,
558 "The matrix type is not supported.");
559 return {buffer.GetNrows(), buffer.GetNcols()};
560 }
561
562 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
563 return {buffer.data(), GetNumOfElements(GetShape(buffer))};
564 }
565
566 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
567 return {buffer.data(), buffer.GetNrows() * buffer.GetNcols()};
568 }
569
570 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
571 if (shape.size() == 2) {
572 buffer.resize(shape[0], shape[1]);
573 } else {
574 buffer.resize(1, GetNumOfElements(shape));
575 }
576 return true;
577 }
578};
579
580template <typename A>
583 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
585 static const bool USES_TEMP_BUFFER = true;
586 using TempBufferType = boost::container::vector<bool>;
587
588 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
589 return {buffer.GetNrows(), buffer.GetNcols()};
590 }
591
595 static gsl::span<ElementType> MakeSpan(BufferType& buffer) = delete;
596
600 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) = delete;
601
602 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
603 if (shape.size() == 2) {
604 buffer.resize(shape[0], shape[1]);
605 } else {
606 buffer.resize(1, GetNumOfElements(shape));
607 }
608 return true;
609 }
610
611 static void CopyToTempBuffer(const BufferType& buffer,
612 std::shared_ptr<TempBufferType>& temp_buffer,
613 size_t offset,
614 size_t count) {
615 assert((buffer.size() >= offset + count) && ("The input buffer is too small."));
616 assert((temp_buffer->size() >= count) && ("The temporary buffer is too small."));
617 std::copy(buffer.begin() + offset, buffer.begin() + offset + count, temp_buffer->begin());
618 }
619
620 static void CopyFromTempBuffer(BufferType& buffer,
621 const std::shared_ptr<TempBufferType>& temp_buffer,
622 size_t offset,
623 size_t count) {
624 assert((buffer.size() >= offset + count) && ("The output buffer is too small."));
625 assert((temp_buffer->size() >= count) && ("The temporary buffer is too small."));
626 std::copy(temp_buffer->begin(), temp_buffer->begin() + count, buffer.begin() + offset);
627 }
628};
629
630template <typename T>
633 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
635 static const bool USES_TEMP_BUFFER = false;
636 using TempBufferType = void;
637
638 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
639 static_assert(
640 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
641 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
642 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
643 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
644 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
645 std::is_same_v<ElementType, RtcDouble> or std::is_same_v<ElementType, RtcString>,
646 "The matrix type is not supported.");
647 return {buffer.GetNrows(), buffer.GetNcols()};
648 }
649
650 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
651 return {buffer.data(), GetNumOfElements(GetShape(buffer))};
652 }
653
654 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
655 return {buffer.data(), buffer.GetNrows() * buffer.GetNcols()};
656 }
657
658 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
659 if (shape.size() == 2 and shape[0] == buffer.GetNrows() and shape[1] == buffer.GetNcols()) {
660 // Cannot resize, but the shape and size is correct, so return true.
661 return true;
662 } else {
663 return false;
664 }
665 }
666};
667
668template <typename T, std::size_t N>
669struct UserTypeHandler<std::array<T, N>> {
670 using BufferType = std::array<T, N>;
671 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
673 static const bool USES_TEMP_BUFFER = false;
674 using TempBufferType = void;
675
676 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
677 static_assert(
678 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
679 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
680 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
681 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
682 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
683 std::is_same_v<ElementType, RtcDouble> or std::is_same_v<ElementType, RtcString> or
684 std::is_same_v<ElementType, std::byte>,
685 "The array type is not supported.");
686 return {buffer.size()};
687 }
688
689 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
690 return {buffer};
691 }
692
693 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
694 return {buffer};
695 }
696
697 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
698 if (shape.size() == 1 and shape[0] == buffer.size()) {
699 // Cannot resize, but the shape and size is correct, so return true.
700 return true;
701 } else {
702 return false;
703 }
704 }
705};
706
707template <std::size_t N>
708struct UserTypeHandler<std::array<char, N>> {
709 using BufferType = std::array<char, N>;
710 using ElementType = std::remove_cv_t<typename BufferType::value_type>;
712 static const bool USES_TEMP_BUFFER = false;
713 using TempBufferType = void;
714
715 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
716 return {buffer.size()};
717 }
718
719 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
720 return {buffer};
721 }
722
723 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
724 return {buffer};
725 }
726
727 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
728 if (shape.size() == 1 and shape[0] == buffer.size()) {
729 // Cannot resize, but the shape and size is correct, so return true.
730 return true;
731 } else {
732 return false;
733 }
734 }
735};
736
737template <typename T, std::size_t N, std::size_t M>
738struct UserTypeHandler<std::array<std::array<T, M>, N>> {
739 using BufferType = std::array<std::array<T, M>, N>;
740 using ElementType = std::remove_cv_t<T>;
742 static const bool USES_TEMP_BUFFER = false;
743 using TempBufferType = void;
744
745 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
746 static_assert(
747 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
748 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
749 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
750 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
751 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
752 std::is_same_v<ElementType, RtcDouble> or std::is_same_v<ElementType, RtcString>,
753 "The array type is not supported.");
754 return {N, M};
755 }
756
757 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
758 static_assert(sizeof(BufferType) == sizeof(ElementType) * N * M);
759 ElementType* begin = &buffer[0][0];
760 return {begin, N * M};
761 }
762
763 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
764 static_assert(sizeof(BufferType) == sizeof(ElementType) * N * M);
765 const ElementType* begin = &buffer[0][0];
766 return {begin, N * M};
767 }
768
769 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
770 if (shape.size() == 2 and shape[0] == N and shape[1] == M) {
771 // Cannot resize, but the shape and size is correct, so return true.
772 return true;
773 } else {
774 return false;
775 }
776 }
777};
778
779// We provide C-style array support in the API on purpose.
780// NOLINTBEGIN(modernize-avoid-c-arrays)
781
785template <typename T, std::size_t N>
786struct UserTypeHandler<T[N]> {
787 using BufferType = T[N];
788 using ElementType = std::remove_cv_t<T>;
790 static const bool USES_TEMP_BUFFER = false;
791 using TempBufferType = void;
792
793 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
794 static_assert(
795 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
796 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
797 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
798 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
799 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
800 std::is_same_v<ElementType, RtcDouble> or std::is_same_v<ElementType, RtcString> or
801 std::is_same_v<ElementType, std::byte>,
802 "The array type is not supported.");
803 return {N};
804 }
805
806 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
807 return {buffer};
808 }
809
810 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
811 return {buffer};
812 }
813
814 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
815 if (shape.size() == 1 and shape[0] == N) {
816 // Cannot resize, but the shape and size is correct, so return true.
817 return true;
818 } else {
819 return false;
820 }
821 }
822};
823
824template <std::size_t N>
825struct UserTypeHandler<char[N]> {
826 using BufferType = char[N];
827 using ElementType = char;
829 static const bool USES_TEMP_BUFFER = false;
830 using TempBufferType = void;
831
832 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
833 return {N};
834 }
835
836 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
837 return {buffer};
838 }
839
840 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
841 return {buffer};
842 }
843
844 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
845 if (shape.size() == 1 and shape[0] == N) {
846 // Cannot resize, but the shape and size is correct, so return true.
847 return true;
848 } else {
849 return false;
850 }
851 }
852};
853
857template <typename T, std::size_t N, std::size_t M>
858struct UserTypeHandler<T[N][M]> {
859 using BufferType = T[N][M];
860 using ElementType = std::remove_cv_t<T>;
862 static const bool USES_TEMP_BUFFER = false;
863 using TempBufferType = void;
864
865 static RtcVectorUInt64 GetShape(const BufferType& buffer) {
866 static_assert(
867 std::is_same_v<ElementType, RtcBool> or std::is_same_v<ElementType, RtcInt8> or
868 std::is_same_v<ElementType, RtcInt16> or std::is_same_v<ElementType, RtcInt32> or
869 std::is_same_v<ElementType, RtcInt64> or std::is_same_v<ElementType, RtcUInt8> or
870 std::is_same_v<ElementType, RtcUInt16> or std::is_same_v<ElementType, RtcUInt32> or
871 std::is_same_v<ElementType, RtcUInt64> or std::is_same_v<ElementType, RtcFloat> or
872 std::is_same_v<ElementType, RtcDouble> or std::is_same_v<ElementType, RtcString>,
873 "The array type is not supported.");
874 return {N, M};
875 }
876
877 static gsl::span<ElementType> MakeSpan(BufferType& buffer) {
878 static_assert(sizeof(BufferType) == sizeof(ElementType) * N * M);
879 return {&buffer[0][0], N * M};
880 }
881
882 static gsl::span<const ElementType> MakeSpan(const BufferType& buffer) {
883 static_assert(sizeof(BufferType) == sizeof(ElementType) * N * M);
884 return {&buffer[0][0], N * M};
885 }
886
887 static bool ResizeBuffer(BufferType& buffer, const RtcVectorUInt64& shape) {
888 if (shape.size() == 2 and shape[0] == N and shape[1] == M) {
889 // Cannot resize, but the shape and size is correct, so return true.
890 return true;
891 } else {
892 return false;
893 }
894 }
895};
896
897// NOLINTEND(modernize-avoid-c-arrays)
898
899} // namespace detail
900
901namespace {
902
909inline bool TypeIsAllowedForValue(const std::type_info& type) {
910 static const std::unordered_set<std::type_index> valid_types = {
911 // Void values are acceptable and represent null values, e.g. equivalent to Python None.
912 std::type_index(typeid(void)),
913 std::type_index(typeid(RtcBool)),
914 std::type_index(typeid(RtcInt8)),
915 std::type_index(typeid(RtcInt16)),
916 std::type_index(typeid(RtcInt32)),
917 std::type_index(typeid(RtcInt64)),
918 std::type_index(typeid(RtcUInt8)),
919 std::type_index(typeid(RtcUInt16)),
920 std::type_index(typeid(RtcUInt32)),
921 std::type_index(typeid(RtcUInt64)),
922 std::type_index(typeid(RtcFloat)),
923 std::type_index(typeid(RtcDouble)),
924 std::type_index(typeid(RtcString))};
925 return valid_types.contains(std::type_index(type));
926}
927
935inline const std::type_info& GetMetaDataReservedKeyType(const std::string& key) {
936 static const std::map<std::string, const std::type_info&> reserved_key_types = {
937 {"type", typeid(std::reference_wrapper<const std::type_info>)},
938 {"shape", typeid(RtcVectorUInt64)},
939 {"timestamp", typeid(RepositoryIf::Timestamp)},
940 {"sequence_id", typeid(RtcUInt64)},
941 {"symlink_target", typeid(DataPointPath)},
942 {"symlinks", typeid(std::set<DataPointPath>)},
943 };
944 auto iter = reserved_key_types.find(key);
945 if (iter != reserved_key_types.end()) {
946 return iter->second;
947 } else {
948 return typeid(void);
949 }
950}
951
961inline void CheckMetaDataTypeForReservedKeys(const std::string& key, const std::type_info& type) {
962 const std::type_info& type_expected = GetMetaDataReservedKeyType(key);
963 if (type_expected == typeid(void)) {
964 throw CII_MAKE_EXCEPTION(RepositoryIf::MetaData::UnsupportedType, type);
965 }
966 if (type != typeid(void) and type_expected != type) {
967 throw CII_MAKE_EXCEPTION(RepositoryIf::MetaData::TypeMismatch, key, type, type_expected);
968 }
969}
970
979inline void CheckMetaDataValueType(const std::string& key, const std::type_info& type) {
980 const std::type_info& type_expected = GetMetaDataReservedKeyType(key);
981 if (type_expected != typeid(void)) {
982 // Dealing with a reserved key. Therefore check that the type being assigned is the one that
983 // is expected for such a key. Note that "type" being effectively a null value is OK.
984 if (type != typeid(void) and type_expected != type) {
985 throw CII_MAKE_EXCEPTION(
986 RepositoryIf::MetaData::TypeMismatch, key, type, type_expected);
987 }
988 } else {
989 // Dealing with a general unreserved user key. Therefore check that the type being assigned
990 // is from the list of allowed types.
991 if (not TypeIsAllowedForValue(type)) {
992 throw CII_MAKE_EXCEPTION(RepositoryIf::MetaData::UnsupportedType, type);
993 }
994 }
995}
996
1008template <typename T>
1009void CheckMetaDataValueType(const std::string& key) {
1010 static_assert(
1011 std::is_same_v<T, RtcBool> or std::is_same_v<T, RtcInt8> or std::is_same_v<T, RtcInt16> or
1012 std::is_same_v<T, RtcInt32> or std::is_same_v<T, RtcInt64> or
1013 std::is_same_v<T, RtcUInt8> or std::is_same_v<T, RtcUInt16> or
1014 std::is_same_v<T, RtcUInt32> or std::is_same_v<T, RtcUInt64> or
1015 std::is_same_v<T, RtcFloat> or std::is_same_v<T, RtcDouble> or
1016 std::is_same_v<T, RtcString> or std::is_same_v<T, RtcBinary> or
1017 std::is_same_v<T, RtcVectorUInt64> or std::is_same_v<T, const std::type_info&> or
1018 std::is_same_v<T, RepositoryIf::Timestamp> or std::is_same_v<T, DataPointPath> or
1019 std::is_same_v<T, std::set<DataPointPath>>,
1020 "The type is not supported for MetaData values.");
1021 if constexpr (std::is_same_v<T, const std::type_info&>) {
1022 // Note (1): type_info can only be applicable to the reserved "type" metadata key.
1023 // Therefore we can call CheckMetaDataTypeForReservedKeys directly.
1024 CheckMetaDataTypeForReservedKeys(key, typeid(std::reference_wrapper<const std::type_info>));
1025 } else {
1026 CheckMetaDataValueType(key, typeid(T));
1027 }
1028}
1029
1037inline bool MetaDataKeyValueIsValid(const std::string& key, const std::any& value) {
1038 const std::type_info& type_expected = GetMetaDataReservedKeyType(key);
1039 if (type_expected != typeid(void)) {
1040 // Dealing with a reserved key. Therefore just check that the type of the value is the same
1041 // as the one expected.
1042 if (value.type() != typeid(void)) {
1043 return type_expected == value.type();
1044 } else {
1045 // If value has a void type, i.e. std::any is unassigned, this is a valid state.
1046 return true;
1047 }
1048 } else {
1049 // Dealing with a general unreserved user key. Therefore check that the value has a type
1050 // from the allowed list.
1051 return TypeIsAllowedForValue(value.type());
1052 }
1053}
1054
1067template <typename T>
1068void CheckSpanSize(const T& span, const RepositoryIf::MetaData& metadata) {
1069 size_t expected_size = detail::GetNumOfElements(metadata["shape"].Cast<RtcVectorUInt64>());
1070 if (expected_size > span.size()) {
1071 throw CII_MAKE_EXCEPTION(RepositoryIf::BufferTooSmall, span.size(), expected_size);
1072 }
1073}
1074
1075} // namespace
1076
1077inline bool RepositoryIf::MetaData::ConstValueProxy::HasValue() const noexcept {
1078 return m_value.has_value();
1079}
1080
1081inline RepositoryIf::MetaData::ConstValueProxy::operator const std::any&() const {
1082 return m_value;
1083}
1084
1085template <typename T>
1086const T& RepositoryIf::MetaData::ConstValueProxy::Cast() const {
1087 CheckMetaDataValueType<T>(m_key);
1088 if constexpr (std::is_same_v<T, const std::type_info&>) {
1089 return std::any_cast<std::reference_wrapper<const std::type_info>>(m_value).get();
1090 } else {
1091 return std::any_cast<const T&>(m_value);
1092 }
1093}
1094
1096 const std::any& value)
1097 : m_key(key), m_value(value) {
1098}
1099
1100inline bool RepositoryIf::MetaData::ValueProxy::HasValue() const noexcept {
1101 return m_value.has_value();
1102}
1103
1104inline RepositoryIf::MetaData::ValueProxy::operator const std::any&() const {
1105 return m_value;
1106}
1107
1108template <typename T>
1109T& RepositoryIf::MetaData::ValueProxy::Cast() {
1110 CheckMetaDataValueType<T>(m_key);
1111 if constexpr (std::is_same_v<T, const std::type_info&>) {
1112 return std::any_cast<std::reference_wrapper<const std::type_info>>(m_value).get();
1113 } else {
1114 return std::any_cast<T&>(m_value);
1115 }
1116}
1117
1118template <typename T>
1119const T& RepositoryIf::MetaData::ValueProxy::Cast() const {
1120 CheckMetaDataValueType<T>(m_key);
1121 if constexpr (std::is_same_v<T, const std::type_info&>) {
1122 return std::any_cast<std::reference_wrapper<const std::type_info>>(m_value).get();
1123 } else {
1124 return std::any_cast<const T&>(m_value);
1125 }
1126}
1127
1128template <typename T>
1130 using U = std::remove_cv_t<std::remove_reference_t<T>>;
1131 if constexpr (std::is_same_v<U, ValueProxy> or std::is_same_v<U, ConstValueProxy>) {
1132 // If assigning from ValueProxy or ConstValueProxy then just copy the value.
1133 CheckMetaDataValueType(m_key, rhs.m_value.type());
1134 m_value = rhs.m_value;
1135 } else if constexpr (std::is_rvalue_reference_v<decltype(rhs)>) {
1136 // Handle the case where we get an rvalue reference, i.e. dealing with a temp object.
1137 // Move/forward where possible to be more efficient.
1138 if constexpr (std::is_same_v<U, std::type_info>) {
1139 // See "Note (1)" above.
1140 CheckMetaDataTypeForReservedKeys(m_key,
1141 typeid(std::reference_wrapper<const std::type_info>));
1142 m_value = std::make_any<std::reference_wrapper<const std::type_info>>(rhs);
1143 } else if constexpr (std::is_same_v<U, std::any>) {
1144 CheckMetaDataValueType(m_key, rhs.type());
1145 m_value = std::forward<T>(rhs);
1146 } else {
1147 CheckMetaDataValueType<U>(m_key);
1148 m_value = std::forward<T>(rhs);
1149 }
1150 } else {
1151 // Handle the case where we get an lvalue reference.
1152 if constexpr (std::is_same_v<U, std::type_info>) {
1153 // See "Note (1)" above.
1154 CheckMetaDataTypeForReservedKeys(m_key,
1155 typeid(std::reference_wrapper<const std::type_info>));
1156 m_value = std::make_any<std::reference_wrapper<const std::type_info>>(rhs);
1157 } else if constexpr (std::is_same_v<U, std::any>) {
1158 CheckMetaDataValueType(m_key, rhs.type());
1159 m_value = rhs;
1160 } else {
1161 CheckMetaDataValueType<U>(m_key);
1162 m_value = rhs;
1163 }
1164 }
1165 assert(MetaDataKeyValueIsValid(m_key, m_value) &&
1166 ("Metadata was modified in an invalid manner."));
1167 return *this;
1168}
1169
1170inline void RepositoryIf::MetaData::ValueProxy::Reset() noexcept {
1171 return m_value.reset();
1172}
1173
1174inline RepositoryIf::MetaData::ValueProxy::ValueProxy(const std::string& key, std::any& value)
1175 : m_key(key), m_value(value) {
1176}
1177
1178template <typename MapIterType, typename ProxyType>
1179typename RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::value_type&
1180RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator*() {
1181 m_pair.emplace(m_iterator->first, ProxyType(m_iterator->first, m_iterator->second));
1182 return m_pair.value();
1183}
1184
1185template <typename MapIterType, typename ProxyType>
1186typename RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::value_type
1187RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator*() const {
1188 return value_type(m_iterator->first, ProxyType(m_iterator->first, m_iterator->second));
1189}
1190
1191template <typename MapIterType, typename ProxyType>
1192typename RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::value_type*
1193RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator->() {
1194 m_pair.emplace(m_iterator->first, ProxyType(m_iterator->first, m_iterator->second));
1195 return &m_pair.value();
1196}
1197
1198template <typename MapIterType, typename ProxyType>
1199const typename RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::value_type*
1200RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator->() const {
1201 m_pair.emplace(m_iterator->first, ProxyType(m_iterator->first, m_iterator->second));
1202 return &m_pair.value();
1203}
1204
1205template <typename MapIterType, typename ProxyType>
1206RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>&
1207RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator++() {
1208 ++m_iterator;
1209 return *this;
1210}
1211
1212template <typename MapIterType, typename ProxyType>
1213RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>
1214RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator++(int) {
1215 auto tmp = *this;
1216 ++m_iterator;
1217 return tmp;
1218}
1219
1220template <typename MapIterType, typename ProxyType>
1221RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>&
1222RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator--() {
1223 --m_iterator;
1224 return *this;
1225}
1226
1227template <typename MapIterType, typename ProxyType>
1228RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>
1229RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator--(int) {
1230 auto tmp = *this;
1231 --m_iterator;
1232 return tmp;
1233}
1234
1235template <typename MapIterType, typename ProxyType>
1236bool RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator==(
1237 const RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>& rhs) const {
1238 return m_iterator == rhs.m_iterator;
1239}
1240
1241template <typename MapIterType, typename ProxyType>
1242bool RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::operator!=(
1243 const RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>& rhs) const {
1244 return m_iterator != rhs.m_iterator;
1245}
1246
1247template <typename MapIterType, typename ProxyType>
1248RepositoryIf::MetaData::IteratorImpl<MapIterType, ProxyType>::IteratorImpl(MapIterType&& iter)
1249 : m_iterator(std::forward<MapIterType>(iter)) {
1250}
1251
1252inline RepositoryIf::MetaData::Iterator::Iterator(RepositoryIf::MetaData::MapType::iterator&& iter)
1253 : RepositoryIf::MetaData::IteratorImpl<RepositoryIf::MetaData::MapType::iterator,
1254 RepositoryIf::MetaData::ValueProxy>(
1255 std::forward<RepositoryIf::MetaData::MapType::iterator>(iter)) {
1256}
1257
1259 RepositoryIf::MetaData::MapType::const_iterator&& iter)
1260 : RepositoryIf::MetaData::IteratorImpl<RepositoryIf::MetaData::MapType::const_iterator,
1261 RepositoryIf::MetaData::ConstValueProxy>(
1262 std::forward<RepositoryIf::MetaData::MapType::const_iterator>(iter)) {
1263}
1264
1266 RepositoryIf::MetaData::MapType::reverse_iterator&& iter)
1267 : RepositoryIf::MetaData::IteratorImpl<RepositoryIf::MetaData::MapType::reverse_iterator,
1268 RepositoryIf::MetaData::ValueProxy>(
1269 std::forward<RepositoryIf::MetaData::MapType::reverse_iterator>(iter)) {
1270}
1271
1273 MapType::const_reverse_iterator&& iter)
1274 : RepositoryIf::MetaData::IteratorImpl<RepositoryIf::MetaData::MapType::const_reverse_iterator,
1275 RepositoryIf::MetaData::ConstValueProxy>(
1276 std::forward<RepositoryIf::MetaData::MapType::const_reverse_iterator>(iter)) {
1277}
1278
1279inline RepositoryIf::MetaData::TypeMismatch::Attributes::Attributes(
1280 const std::string& key, const std::type_info& type_used, const std::type_info& type_expected)
1281 : m_key(key), m_type_used(type_used), m_type_expected(type_expected) {
1282}
1283
1285 return m_metadata.empty();
1286}
1287
1288inline size_t RepositoryIf::MetaData::GetSize() const noexcept {
1289 return m_metadata.size();
1290}
1291
1292inline bool RepositoryIf::MetaData::Contains(const std::string& key) const {
1293 return m_metadata.contains(key);
1294}
1295
1296template <typename T>
1297auto& RepositoryIf::MetaData::Insert(const std::string& key, T&& value) {
1298 std::string key_copy = key;
1299 return Insert(std::move(key_copy), std::forward<T>(value));
1300}
1301
1302template <typename T>
1303auto& RepositoryIf::MetaData::Insert(std::string&& key, T&& value) {
1304 using U = std::remove_cv_t<std::remove_reference_t<T>>;
1305 decltype(m_metadata)::iterator iter;
1306 bool inserted;
1307 if constexpr (std::is_same_v<U, std::type_info>) {
1308 // Handle the case where we are assigning a type_info as the value. See "Note (1)" above.
1309 CheckMetaDataTypeForReservedKeys(key, typeid(std::reference_wrapper<const std::type_info>));
1310 auto type = std::make_any<std::reference_wrapper<const std::type_info>>(value);
1311 std::tie(iter, inserted) = m_metadata.try_emplace(std::forward<std::string>(key), type);
1312 } else {
1313 CheckMetaDataValueType<U>(key);
1314 std::tie(iter, inserted) =
1315 m_metadata.try_emplace(std::forward<std::string>(key), std::forward<T>(value));
1316 }
1317 if (not inserted) {
1318 // The try_emplace documentation indicates that it does not move the key if the insertion
1319 // did not occur. Therefore the following std::forward is OK at this point.
1320 // NOLINTNEXTLINE(bugprone-use-after-move)
1321 throw CII_MAKE_EXCEPTION(KeyAlreadyExists, std::forward<std::string>(key));
1322 }
1323 assert(MetaDataKeyValueIsValid(iter->first, iter->second) &&
1324 ("Metadata was modified in an invalid manner."));
1325 if constexpr (std::is_same_v<U, std::type_info>) {
1326 return std::any_cast<std::reference_wrapper<const std::type_info>>(iter->second).get();
1327 } else {
1328 return std::any_cast<U&>(iter->second);
1329 }
1330}
1331
1332// The following methods are for STL compatibility and therefore must use lower case.
1333// NOLINTBEGIN(readability-identifier-naming)
1335 return m_metadata.begin();
1336};
1337
1339 return m_metadata.begin();
1340};
1341
1343 return m_metadata.cbegin();
1344};
1345
1347 return m_metadata.end();
1348};
1349
1351 return m_metadata.end();
1352};
1353
1355 return m_metadata.cend();
1356};
1357
1359 return m_metadata.rbegin();
1360};
1361
1363 return m_metadata.rbegin();
1364};
1365
1368 return m_metadata.crbegin();
1369};
1370
1372 return m_metadata.rend();
1373};
1374
1376 return m_metadata.rend();
1377};
1378
1380 return m_metadata.crend();
1381};
1382// NOLINTEND(readability-identifier-naming)
1383
1384template <typename T>
1386 const DataPointPath& path,
1387 const T& initial_value,
1388 std::optional<std::reference_wrapper<const MetaData>> metadata,
1389 const CallbackType& callback) {
1390 using TypeHandler = detail::UserTypeHandler<T>;
1391
1393
1394 MetaData merged_metadata;
1395 if (metadata.has_value()) {
1396 merged_metadata = metadata.value();
1397 }
1398 auto shape = TypeHandler::GetShape(initial_value);
1399 merged_metadata["type"] = typeid(typename TypeHandler::DataPointType);
1400 merged_metadata["shape"] = shape;
1401
1402 if constexpr (TypeHandler::USES_TEMP_BUFFER) {
1403 // If the type handler indicates it needs a temporary buffer, then we need to create it from
1404 // the initial_value buffer by resizing it appropriately and copying the data over.
1405 // Next, we create a span compatible with the new temporary buffer (not a span from the
1406 // original initial_value!), which is passed onto the actual request.
1407 using TempBufferType = typename TypeHandler::TempBufferType;
1408 using TempBufferHandler = detail::UserTypeHandler<TempBufferType>;
1409 auto temp_buffer = std::make_shared<TempBufferType>();
1410 bool buffer_resized = TempBufferHandler::ResizeBuffer(*temp_buffer, shape);
1411 if (not buffer_resized) {
1412 throw CII_MAKE_EXCEPTION(
1414 fmt::format("Resizing of a '{}' buffer should have succeeded.",
1415 boost::core::demangle(typeid(TempBufferType).name())));
1416 }
1417 auto count = detail::GetNumOfElements(shape);
1418 TypeHandler::CopyToTempBuffer(initial_value, temp_buffer, 0, count);
1419 auto span = TempBufferHandler::MakeSpan(*temp_buffer);
1420
1421 // A customised callback is also needed to cleanup the buffer once the request has
1422 // completed. Also need to remember to call the actual user callback if one was provided.
1423 auto cb = [temp_buffer, callback](const DataPointPath& path) mutable {
1424 temp_buffer.reset();
1425 if (callback) {
1426 callback(path);
1427 }
1428 };
1429
1430 using ElementType = typename TempBufferHandler::ElementType;
1432 path, std::move(span), std::move(merged_metadata), std::move(cb)});
1433 } else {
1434 // If a temporary buffer is not needed then just create the appropriate span directly from
1435 // the initial_value buffer and register the request.
1436 auto span = TypeHandler::MakeSpan(initial_value);
1437 using ElementType = typename TypeHandler::ElementType;
1439 path, std::move(span), std::move(merged_metadata), callback});
1440 }
1441}
1442
1443template <typename T>
1445 const DataPointPath& path,
1446 T& buffer,
1447 std::optional<std::reference_wrapper<MetaData>> metadata,
1448 const CallbackType& callback) const {
1449 // Note (2): Just call the internal implementation method. The reason for having an internal
1450 // implementation method is to avoid compiler errors about ambiguous methods when trying to
1451 // specialise this template method for std::any. There are two methods in the public API, one
1452 // that takes an lvalue buffer argument and the deleted method signature that takes an rvalue
1453 // buffer argument. Trying to specialise the public method leads to the compiler error.
1454 // This ambiguity is avoided by having just one internal implementation method, and specialising
1455 // the internal method.
1456 ReadDataPointImpl(path, buffer, metadata, callback);
1457}
1458
1459template <typename T>
1460void RepositoryIf::BatchRequest::ReadDataPointImpl(
1461 const DataPointPath& path,
1462 T& buffer,
1463 std::optional<std::reference_wrapper<MetaData>> metadata,
1464 const CallbackType& callback) const {
1465 static_assert(not std::is_same_v<T, std::string_view>,
1466 "It is not possible to read data from a datapoint into a read-only string_view.");
1467
1468 using TypeHandler = detail::UserTypeHandler<T>;
1469 using DataPointType = typename TypeHandler::DataPointType; // Expected type of the data point.
1470
1472
1473 if constexpr (TypeHandler::USES_TEMP_BUFFER) {
1474 using TempBufferType = typename TypeHandler::TempBufferType;
1475 using TempBufferHandler = detail::UserTypeHandler<TempBufferType>;
1476 auto temp_buffer = std::make_shared<TempBufferType>();
1477
1478 // If a temporary buffer is needed to handle the given data type T, we need to setup a
1479 // prepare_buffer callback that will allocate the temporary buffer and resize it to the
1480 // required size.
1481 // Note: "buffer" is maintained by the user, therefore its lifetime outlasts the request
1482 // and this callback invocation, therefore it can be captured by reference. The other
1483 // "temp_buffer" and user provided "callback" must be captured by value to have a copy that
1484 // will have a lifetime compatible with the invocation of the "prepare_buffer" and "cb"
1485 // functions.
1486 auto prepare_buffer = [&, temp_buffer](const MetaData& md) {
1487 assert((md.Contains("type")) && ("Adapter must provide the type in the metadata."));
1488 assert((md.Contains("shape")) && ("Adapter must provide the shape in the metadata."));
1489 if (md["type"].Cast<const std::type_info&>() != typeid(DataPointType)) {
1490 throw CII_MAKE_EXCEPTION(IncompatibleType, "Datapoint type mismatch.");
1491 }
1492 const auto& shape = md["shape"].Cast<RtcVectorUInt64>();
1493 TypeHandler::ResizeBuffer(buffer, shape);
1494 TempBufferHandler::ResizeBuffer(*temp_buffer, shape);
1495 // Note: no need to check if buffer was actually resized at this point.
1496 // This is effectively checked by the call to CheckSpanSize later.
1497 auto span = TempBufferHandler::MakeSpan(*temp_buffer);
1498 CheckSpanSize(span, md);
1499 return span;
1500 };
1501
1502 // In the callback we copy the data from the temporary buffer into the original buffer.
1503 // Once the data is copied, cleanup the temporary buffer and remember to call the actual
1504 // user callback if one was provided.
1505 auto cb = [&, temp_buffer, callback](const DataPointPath& path) mutable {
1506 auto shape = TempBufferHandler::GetShape(*temp_buffer);
1507 auto count = detail::GetNumOfElements(shape);
1508 TypeHandler::CopyFromTempBuffer(buffer, temp_buffer, 0, count);
1509 temp_buffer.reset();
1510 if (callback) {
1511 callback(path);
1512 }
1513 };
1514
1515 using ElementType = typename TempBufferHandler::ElementType;
1516 m_requests.push_back(detail::ReadRequest<ElementType>{
1517 path, std::move(prepare_buffer), metadata, std::move(cb)});
1518 } else {
1519 auto prepare_buffer = [&](const MetaData& md) {
1520 assert((md.Contains("type")) && ("Adapter must provide the type in the metadata."));
1521 assert((md.Contains("shape")) && ("Adapter must provide the shape in the metadata."));
1522 if (md["type"].Cast<const std::type_info&>() != typeid(DataPointType)) {
1523 throw CII_MAKE_EXCEPTION(IncompatibleType, "Datapoint type mismatch.");
1524 }
1525 TypeHandler::ResizeBuffer(buffer, md["shape"].Cast<RtcVectorUInt64>());
1526 auto span = TypeHandler::MakeSpan(buffer);
1527 CheckSpanSize(span, md);
1528 return span;
1529 };
1530
1531 using ElementType = typename TypeHandler::ElementType;
1532 m_requests.push_back(
1533 detail::ReadRequest<ElementType>{path, std::move(prepare_buffer), metadata, callback});
1534 }
1535}
1536
1537template <typename T>
1539 const DataPointPath& path,
1540 const T& buffer,
1541 std::optional<std::reference_wrapper<MetaData>> metadata,
1542 const CallbackType& callback) {
1543 using TypeHandler = detail::UserTypeHandler<T>;
1544
1546
1547 MetaData merged_metadata;
1548 if (metadata.has_value()) {
1549 merged_metadata = metadata.value();
1550 }
1551 auto shape = TypeHandler::GetShape(buffer);
1552 merged_metadata["type"] = typeid(typename TypeHandler::DataPointType);
1553 merged_metadata["shape"] = shape;
1554
1555 if constexpr (TypeHandler::USES_TEMP_BUFFER) {
1556 // If the type handler indicates it needs a temporary buffer, then create it, resize it to
1557 // the required size and copy the data from the input buffer into the temporary buffer.
1558 // Next, we create a span compatible with the new temporary buffer (not a span from the
1559 // original initial_value!), which is passed onto the actual request.
1560 using TempBufferType = typename TypeHandler::TempBufferType;
1561 using TempBufferHandler = detail::UserTypeHandler<TempBufferType>;
1562 auto temp_buffer = std::make_shared<TempBufferType>();
1563 bool buffer_resized = TempBufferHandler::ResizeBuffer(*temp_buffer, shape);
1564 if (not buffer_resized) {
1565 throw CII_MAKE_EXCEPTION(
1567 fmt::format("Resizing of a '{}' buffer should have succeeded.",
1568 boost::core::demangle(typeid(TempBufferType).name())));
1569 }
1570 auto count = detail::GetNumOfElements(shape);
1571 TypeHandler::CopyToTempBuffer(buffer, temp_buffer, 0, count);
1572 auto span = TempBufferHandler::MakeSpan(*temp_buffer);
1573
1574 // A customised callback is also needed to cleanup the buffer once the request has
1575 // completed. Remember to call the actual user callback if one was provided.
1576 auto cb = [temp_buffer, callback](const DataPointPath& path) mutable {
1577 temp_buffer.reset();
1578 if (callback) {
1579 callback(path);
1580 }
1581 };
1582
1583 using ElementType = typename TempBufferHandler::ElementType;
1585 path, std::move(span), std::move(merged_metadata), metadata, std::move(cb)});
1586 } else {
1587 auto span = TypeHandler::MakeSpan(buffer);
1588 using ElementType = typename TypeHandler::ElementType;
1590 path, std::move(span), std::move(merged_metadata), metadata, callback});
1591 }
1592}
1593
1594template <typename T>
1596 const DataPointPath& path,
1597 T& buffer,
1598 size_t first,
1599 size_t last,
1600 size_t d_first,
1601 std::optional<std::reference_wrapper<MetaData>> metadata,
1602 const CallbackType& callback) const {
1603 // See "Note (2)" above.
1604 PartialReadDataPointImpl(path, buffer, first, last, d_first, metadata, callback);
1605}
1606
1607template <typename T>
1608void RepositoryIf::BatchRequest::PartialReadDataPointImpl(
1609 const DataPointPath& path,
1610 T& buffer,
1611 size_t first,
1612 size_t last,
1613 size_t d_first,
1614 std::optional<std::reference_wrapper<MetaData>> metadata,
1615 const CallbackType& callback) const {
1616 using TypeHandler = detail::UserTypeHandler<T>;
1617
1619
1620 auto shape = TypeHandler::GetShape(buffer);
1621 size_t buffer_size = detail::GetNumOfElements(shape);
1622 size_t expected_size = d_first + last - first;
1623 if (first > last or expected_size > buffer_size) {
1624 throw CII_MAKE_EXCEPTION(BufferTooSmall,
1625 buffer_size,
1626 expected_size,
1627 "Make sure first <= last and d_first + last - first <= number of "
1628 "elements in the output buffer.");
1629 }
1630 MetaData input_metadata;
1631 input_metadata["type"] = typeid(typename TypeHandler::DataPointType);
1632 input_metadata["shape"] = shape;
1633
1634 if constexpr (TypeHandler::USES_TEMP_BUFFER) {
1635 // If a temporary buffer is needed to handle the given data type T, we create the temporary
1636 // buffer and resize it as a one dimensional array. It should hold just enough elements to
1637 // store the actual number that will be read from the datapoint.
1638 // Next, we create a span compatible with the new temporary buffer (not a span from the
1639 // original output buffer!), which is passed onto the actual request. Thus, the repository
1640 // adapter will actually write into the temporary buffer, from which we later copy back into
1641 // the original output buffer.
1642 using TempBufferType = typename TypeHandler::TempBufferType;
1643 using TempBufferHandler = detail::UserTypeHandler<TempBufferType>;
1644 auto temp_buffer = std::make_shared<TempBufferType>();
1645 bool buffer_resized = TempBufferHandler::ResizeBuffer(*temp_buffer, {last - first});
1646 if (not buffer_resized) {
1647 throw CII_MAKE_EXCEPTION(
1648 RepositoryIf::ServiceFailure,
1649 fmt::format("Resizing of a '{}' buffer should have succeeded.",
1650 boost::core::demangle(typeid(TempBufferType).name())));
1651 }
1652 auto span = TempBufferHandler::MakeSpan(*temp_buffer);
1653 assert((span.size() >= last - first) &&
1654 ("The temporary buffer was not resized correctly."));
1655
1656 // In the callback we copy the data from the temporary buffer into the original buffer.
1657 // Note: the temporary buffer is treated as a one dimensional array.
1658 // Once the data is copied, cleanup the temporary buffer and remember to call the actual
1659 // user callback if one was provided.
1660 auto cb =
1661 [&, temp_buffer, callback, first, last, d_first](const DataPointPath& path) mutable {
1662 TypeHandler::CopyFromTempBuffer(buffer, temp_buffer, d_first, last - first);
1663 temp_buffer.reset();
1664 if (callback) {
1665 callback(path);
1666 }
1667 };
1668
1669 using ElementType = typename TempBufferHandler::ElementType;
1670 m_requests.push_back(detail::PartialReadRequest<ElementType>{
1671 path, span, input_metadata, metadata, first, std::move(cb)});
1672 } else {
1673 auto span = TypeHandler::MakeSpan(buffer);
1674 using ElementType = typename TypeHandler::ElementType;
1675 m_requests.push_back(detail::PartialReadRequest<ElementType>{
1676 path, span.subspan(d_first, last - first), input_metadata, metadata, first, callback});
1677 }
1678}
1679
1680template <typename T>
1682 const DataPointPath& path,
1683 const T& buffer,
1684 size_t first,
1685 size_t last,
1686 size_t d_first,
1687 std::optional<std::reference_wrapper<MetaData>> metadata,
1688 const CallbackType& callback) {
1689 using TypeHandler = detail::UserTypeHandler<T>;
1690
1692
1693 auto shape = TypeHandler::GetShape(buffer);
1694 size_t buffer_size = detail::GetNumOfElements(shape);
1695 if (first > last or last > buffer_size) {
1696 throw CII_MAKE_EXCEPTION(
1698 buffer_size,
1699 last,
1700 "Make sure first <= last <= number of elements in the input buffer.");
1701 }
1702
1703 MetaData merged_metadata;
1704 if (metadata.has_value()) {
1705 merged_metadata = metadata.value();
1706 }
1707 merged_metadata["type"] = typeid(typename TypeHandler::DataPointType);
1708 merged_metadata["shape"] = shape;
1709
1710 if constexpr (TypeHandler::USES_TEMP_BUFFER) {
1711 // If a temporary buffer is needed to handle the given data type T, we create the temporary
1712 // buffer and resize it as a one dimensional array. It should hold just enough elements to
1713 // store the actual number that will be written to the datapoint.
1714 // The data from the original input buffer is then copied into the temporary buffer.
1715 // Next, we create a span compatible with the new temporary buffer (not a span from the
1716 // original input buffer!), which is passed onto the actual request.
1717 using TempBufferType = typename TypeHandler::TempBufferType;
1718 using TempBufferHandler = detail::UserTypeHandler<TempBufferType>;
1719 auto temp_buffer = std::make_shared<TempBufferType>();
1720 bool buffer_resized = TempBufferHandler::ResizeBuffer(*temp_buffer, {last - first});
1721 if (not buffer_resized) {
1722 throw CII_MAKE_EXCEPTION(
1724 fmt::format("Resizing of a '{}' buffer should have succeeded.",
1725 boost::core::demangle(typeid(TempBufferType).name())));
1726 }
1727 TypeHandler::CopyToTempBuffer(buffer, temp_buffer, 0, last - first);
1728 auto span = TempBufferHandler::MakeSpan(*temp_buffer);
1729 assert((span.size() >= last - first) &&
1730 ("The temporary buffer was not resized correctly."));
1731
1732 // A customised callback is also needed to cleanup the buffer once the request has
1733 // completed. Remember to call the actual user callback if one was provided.
1734 auto cb = [temp_buffer, callback](const DataPointPath& path) mutable {
1735 temp_buffer.reset();
1736 if (callback) {
1737 callback(path);
1738 }
1739 };
1740
1741 using ElementType = typename TempBufferHandler::ElementType;
1743 path, span, std::move(merged_metadata), d_first, metadata, std::move(cb)});
1744 } else {
1745 auto span = TypeHandler::MakeSpan(buffer);
1746 using ElementType = typename TypeHandler::ElementType;
1747 m_requests.push_back(
1749 span.subspan(first, last - first),
1750 std::move(merged_metadata),
1751 d_first,
1752 metadata,
1753 callback});
1754 }
1755}
1756
1757// The following template specialisations are forward declarations for handling std::any as the
1758// buffer type. Their implementations are in the .cpp file for correct linking.
1759template <>
1761 const DataPointPath& path,
1762 const std::any& initial_value,
1763 std::optional<std::reference_wrapper<const MetaData>> metadata,
1764 const CallbackType& callback);
1765
1766template <>
1767void RepositoryIf::BatchRequest::ReadDataPointImpl(
1768 const DataPointPath& path,
1769 std::any& buffer,
1770 std::optional<std::reference_wrapper<MetaData>> metadata,
1771 const CallbackType& callback) const;
1772
1773template <>
1775 const DataPointPath& path,
1776 const std::any& buffer,
1777 std::optional<std::reference_wrapper<MetaData>> metadata,
1778 const CallbackType& callback);
1779
1780template <>
1781void RepositoryIf::BatchRequest::PartialReadDataPointImpl(
1782 const DataPointPath& path,
1783 std::any& buffer,
1784 size_t first,
1785 size_t last,
1786 size_t d_first,
1787 std::optional<std::reference_wrapper<MetaData>> metadata,
1788 const CallbackType& callback) const;
1789
1790template <>
1792 const DataPointPath& path,
1793 const std::any& buffer,
1794 size_t first,
1795 size_t last,
1796 size_t d_first,
1797 std::optional<std::reference_wrapper<MetaData>> metadata,
1798 const CallbackType& callback);
1799
1800template <typename Rep, typename Period>
1801bool RepositoryIf::BatchResponse::WaitFor(const std::chrono::duration<Rep, Period>& timeout) {
1802 // Calculate a timepoint in future that will correspond to the requested timeout period and then
1803 // invoke the WaitUntil implementation. We do it this way since we may have multiple futures to
1804 // check. Using WaitUntil will make sure the original timeout period is more closely adhered to
1805 // in such a case.
1806 auto maxtime = Clock::now();
1807 maxtime += std::chrono::duration_cast<Clock::duration>(timeout);
1808 return WaitUntil(maxtime);
1809}
1810
1811template <typename Clk, typename Duration>
1812bool RepositoryIf::BatchResponse::WaitUntil(const std::chrono::time_point<Clk, Duration>& timeout) {
1813 // Check if every future in the responses list is ready.
1814 for (auto& response : m_responses) {
1815 if (response.wait_until(timeout) != std::future_status::ready) {
1816 return false;
1817 }
1818 }
1819 // If we got here then all futures are ready, therefore the call to Wait() should complete
1820 // without blocking.
1821 Wait();
1822 return true;
1823}
1824
1825template <typename T>
1827 static_assert(not std::is_same_v<T, std::any>,
1828 "Cannot create a datapoint using an empty std::any. Datapoint type is unknown.");
1829 BatchRequest req;
1830 T value{};
1831 req.CreateDataPoint(path, value);
1832 SendRequest(req).Wait();
1833}
1834
1835template <typename T>
1836void RepositoryIf::CreateDataPoint(const DataPointPath& path, const T& initial_value) {
1837 BatchRequest req;
1838 req.CreateDataPoint(path, initial_value);
1839 SendRequest(req).Wait();
1840}
1841
1842template <typename T>
1844 BatchRequest req;
1845 T result;
1846 // If we are dealing with T == std::any then fill the result buffer with an initial object of
1847 // the appropriate type, i.e. the datapoint's type.
1848 if constexpr (std::is_same_v<T, std::any>) {
1849 MetaData metadata;
1850 BatchRequest meta_req;
1851 meta_req.ReadMetaData(path, metadata);
1852 SendRequest(meta_req).Wait();
1853 result = MakeAnyBuffer(metadata);
1854 }
1855 req.ReadDataPoint(path, result);
1856 SendRequest(req).Wait();
1857 return result;
1858}
1859
1860template <typename T>
1861std::optional<T> RepositoryIf::TryGetDataPoint(const DataPointPath& path) const {
1862 if (DataPointExists(path)) {
1863 return GetDataPoint<T>(path);
1864 }
1865 return std::nullopt;
1866}
1867
1868template <typename T>
1869void RepositoryIf::SetDataPoint(const DataPointPath& path, const T& value) {
1870 BatchRequest req;
1871 req.WriteDataPoint(path, value);
1872 SendRequest(req).Wait();
1873}
1874
1875template <typename T>
1876void RepositoryIf::ReadDataPoint(const DataPointPath& path, T& buffer) const {
1877 // If we are dealing with T == std::any and the buffer is empty, then fill it with an initial
1878 // object of the appropriate type, i.e. the datapoint's type.
1879 if constexpr (std::is_same_v<T, std::any>) {
1880 if (not buffer.has_value()) {
1881 MetaData metadata;
1882 BatchRequest meta_req;
1883 meta_req.ReadMetaData(path, metadata);
1884 SendRequest(meta_req).Wait();
1885 buffer = MakeAnyBuffer(metadata);
1886 }
1887 }
1888 BatchRequest req;
1889 req.ReadDataPoint(path, buffer);
1890 SendRequest(req).Wait();
1891}
1892
1893template <typename T>
1894void RepositoryIf::WriteDataPoint(const DataPointPath& path, const T& buffer) {
1895 BatchRequest req;
1896 req.WriteDataPoint(path, buffer);
1897 SendRequest(req).Wait();
1898}
1899
1900template <typename... T>
1901void RepositoryIf::WriteDataPoints(const T&... args) {
1902 std::optional<std::reference_wrapper<const DataPointPath>> path_ref;
1903 BatchRequest req;
1904 (
1905 [&] {
1906 if constexpr (std::is_same_v<const DataPointPath&, decltype(args)>) {
1907 path_ref = args;
1908 } else {
1909 req.WriteDataPoint(path_ref.value().get(), args);
1910 }
1911 }(),
1912 ...);
1913 SendRequest(req).Wait();
1914}
1915
1916template <typename... T>
1917void RepositoryIf::ReadDataPoints(T&... args) const {
1918 std::optional<std::reference_wrapper<const DataPointPath>> path_ref;
1919
1920 // If there are std::any arguments given and the corresponding buffers are empty, then fill them
1921 // with an initial object of the appropriate type, i.e. the datapoint's type.
1922 if constexpr ((std::is_same_v<T, std::any> or ...)) {
1923 using Entry = std::pair<std::reference_wrapper<std::any>, MetaData>;
1924 std::vector<Entry> any_buffers;
1925 // Make sure to reserve enough space in any_buffers to prevent reallocations, otherwise
1926 // the memory addresses given to the ReadMetaData calls will become invalidated.
1927 any_buffers.reserve(sizeof...(T));
1928 BatchRequest meta_req;
1929 (
1930 [&] {
1931 if constexpr (std::is_same_v<DataPointPath&, decltype(args)>) {
1932 path_ref = args;
1933 } else if constexpr (std::is_same_v<std::any&, decltype(args)>) {
1934 if (not args.has_value()) {
1935 auto& metadata = any_buffers.emplace_back(Entry(args, MetaData{})).second;
1936 meta_req.ReadMetaData(path_ref.value().get(), metadata);
1937 }
1938 }
1939 }(),
1940 ...);
1941 if (not any_buffers.empty()) {
1942 SendRequest(meta_req).Wait();
1943 for (auto [buffer, metadata] : any_buffers) {
1944 buffer.get() = MakeAnyBuffer(metadata);
1945 }
1946 }
1947 }
1948
1949 BatchRequest req;
1950 (
1951 [&] {
1952 if constexpr (std::is_same_v<DataPointPath&, decltype(args)>) {
1953 path_ref = args;
1954 } else {
1955 req.ReadDataPoint(path_ref.value().get(), args);
1956 }
1957 }(),
1958 ...);
1959 SendRequest(req).Wait();
1960}
1961
1962} // namespace rtctk::componentFramework
This class provides a wrapper for a data point path.
Definition dataPointPath.hpp:77
bool IsAbsolutePath() const
Checks whether the path is an absolute path.
Definition dataPointPath.cpp:145
A buffer class representing 2D matrix data.
Definition matrixBuffer.hpp:28
size_type GetNcols() const
Definition matrixBuffer.hpp:89
size_type GetNrows() const
Definition matrixBuffer.hpp:85
constexpr void resize(size_type n, size_type m)
Definition matrixBuffer.hpp:60
A span referencing a 2D matrix buffer.
Definition matrixSpan.hpp:36
size_type GetNrows() const
Definition matrixSpan.hpp:156
size_type GetNcols() const
Definition matrixSpan.hpp:160
An object representing one or more asynchronous I/O requests to a repository.
Definition repositoryIf.hpp:634
RequestList m_requests
Definition repositoryIf.hpp:922
void WriteDataPoint(const DataPointPath &path, const T &buffer, std::optional< std::reference_wrapper< MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr)
Definition repositoryIf.ipp:1538
void ReadDataPoint(const DataPointPath &path, T &buffer, std::optional< std::reference_wrapper< MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr) const
Definition repositoryIf.ipp:1444
void PartialReadDataPoint(const DataPointPath &path, T &buffer, size_t first, size_t last, size_t d_first, std::optional< std::reference_wrapper< MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr) const
Definition repositoryIf.ipp:1595
void ReadMetaData(const DataPointPath &path, MetaData &metadata, const CallbackType &callback=nullptr) const
Definition repositoryIf.cpp:367
void PartialWriteDataPoint(const DataPointPath &path, const T &buffer, size_t first, size_t last, size_t d_first, std::optional< std::reference_wrapper< MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr)
Definition repositoryIf.ipp:1681
void CreateDataPoint(const DataPointPath &path, const T &initial_value, std::optional< std::reference_wrapper< const MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr)
Definition repositoryIf.ipp:1385
void Wait()
Definition repositoryIf.cpp:645
ResponseList m_responses
Definition repositoryIf.hpp:957
bool WaitFor(const std::chrono::duration< Rep, Period > &timeout)
Definition repositoryIf.ipp:1801
bool WaitUntil(const std::chrono::time_point< Clk, Duration > &timeout)
Definition repositoryIf.ipp:1812
Constant version of the bidirectional forward iterator returned by the cbegin/cend methods.
Definition repositoryIf.hpp:361
Constant version of the bidirectional reverse iterator returned by the crbegin/crend methods.
Definition repositoryIf.hpp:382
A read-only interface class to an underlying metadata value.
Definition repositoryIf.hpp:154
Bidirectional forward iterator returned by the begin/end methods.
Definition repositoryIf.hpp:350
Exception indicating that the metadata already contains the given key.
Definition repositoryIf.hpp:403
Bidirectional reverse iterator returned by the rbegin/rend methods.
Definition repositoryIf.hpp:371
Exception indicating that a value with the wrong type was being assigned to a reserved key.
Definition repositoryIf.hpp:416
Exception indicating that an unsupported type was used for the metadata value.
Definition repositoryIf.hpp:441
Interface class to an underlying metadata value.
Definition repositoryIf.hpp:208
Class for passing/receiving metadata to/from the repository.
Definition repositoryIf.hpp:146
ConstIterator cbegin() const noexcept
Return a read-only forward iterator to the beginning of the metadata entries.
Definition repositoryIf.ipp:1342
MetaData & operator=(const MetaData &rhs)=default
ValueProxy Insert(const std::string &key)
Add a new metadata key.
Definition repositoryIf.cpp:244
size_t GetSize() const noexcept
Get the number of entries in the metadata.
Definition repositoryIf.ipp:1288
Iterator end()
Return a forward iterator to the end of the metadata entries.
Definition repositoryIf.ipp:1346
ReverseIterator rbegin()
Return a reverse iterator to the beginning of the metadata entries.
Definition repositoryIf.ipp:1358
Iterator begin()
Return a forward iterator to the beginning of the metadata entries.
Definition repositoryIf.ipp:1334
ConstReverseIterator crend() const noexcept
Return a read-only reverse iterator to the end of the metadata entries.
Definition repositoryIf.ipp:1379
ConstReverseIterator crbegin() const noexcept
Return a read-only reverse iterator to the beginning of the metadata entries.
Definition repositoryIf.ipp:1367
bool Empty() const
Check if the metadata contains any values.
Definition repositoryIf.ipp:1284
ReverseIterator rend()
Return a reverse iterator to the end of the metadata entries.
Definition repositoryIf.ipp:1371
bool Contains(const std::string &key) const
Check if the metadata contains a specific key.
Definition repositoryIf.ipp:1292
ConstIterator cend() const noexcept
Return a read-only forward iterator to the end of the metadata entries.
Definition repositoryIf.ipp:1354
std::optional< T > TryGetDataPoint(const DataPointPath &path) const
Fetches a datapoint from the repository.
Definition repositoryIf.ipp:1861
Clock::time_point Timestamp
Definition repositoryIf.hpp:58
void WriteDataPoints(const T &... args)
Definition repositoryIf.ipp:1901
T GetDataPoint(const DataPointPath &path) const
Fetches a datapoint from the repository.
Definition repositoryIf.ipp:1843
void ReadDataPoints(T &... args) const
Definition repositoryIf.ipp:1917
void CreateDataPoint(const DataPointPath &path)
Creates a new empty datapoint in the repository.
Definition repositoryIf.ipp:1826
static std::any MakeAnyBuffer(const MetaData &metadata)
Helper method to create an std::any buffer compatible with a specific datapoint.
Definition repositoryIf.cpp:897
void SetDataPoint(const DataPointPath &path, const T &value)
Sets a datapoint in the repository.
Definition repositoryIf.ipp:1869
void WriteDataPoint(const DataPointPath &path, const T &buffer)
Writes a datapoint to the repository.
Definition repositoryIf.ipp:1894
BatchResponse SendRequest(const BatchRequest &request)
Definition repositoryIf.cpp:669
void ReadDataPoint(const DataPointPath &path, T &buffer) const
Reads a datapoint from the repository.
Definition repositoryIf.ipp:1876
std::function< void(const DataPointPath &)> CallbackType
Signature of the callback functions that can be registered with the repository requests.
Definition repositoryIf.hpp:61
bool DataPointExists(const DataPointPath &path) const
Checks for the existence of a datapoint in the repository.
Definition repositoryIf.cpp:766
Definition measurable.hpp:26
RtcUInt64 GetNumOfElements(const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:136
void EnsureAbsolutePath(const DataPointPath &path)
Definition repositoryIf.ipp:144
Definition commandReplier.cpp:22
RepositoryIf::MetaData MetaData
Definition oldbAdapter.cpp:55
void to_json(JsonPayload &j, const DataPointPath &v)
Definition dataPointPath.cpp:218
nlohmann::json JsonPayload
Type requirements:
Definition jsonPayload.hpp:25
std::int64_t RtcInt64
Definition basicTypes.hpp:41
std::int16_t RtcInt16
Definition basicTypes.hpp:39
std::uint16_t RtcUInt16
Definition basicTypes.hpp:43
float RtcFloat
Definition basicTypes.hpp:46
std::int32_t RtcInt32
Definition basicTypes.hpp:40
componentFramework::MatrixBuffer< T > RtcMatrix
Definition basicTypes.hpp:35
std::int8_t RtcInt8
Definition basicTypes.hpp:38
std::string RtcString
Definition basicTypes.hpp:48
std::vector< T > RtcVector
Definition basicTypes.hpp:29
bool RtcBool
Definition basicTypes.hpp:37
std::uint32_t RtcUInt32
Definition basicTypes.hpp:44
RtcMatrix< RtcBool > RtcMatrixBool
Definition basicTypes.hpp:62
std::uint8_t RtcUInt8
Definition basicTypes.hpp:42
RtcVector< RtcBool > RtcVectorBool
Definition basicTypes.hpp:50
RtcVector< RtcUInt64 > RtcVectorUInt64
Definition basicTypes.hpp:58
std::uint64_t RtcUInt64
Definition basicTypes.hpp:45
double RtcDouble
Definition basicTypes.hpp:47
Definition ddsSub.hpp:156
gsl::span< const T > data
Definition repositoryIf.ipp:43
DataPointPath path
Definition repositoryIf.ipp:42
T ElementType
Definition repositoryIf.ipp:41
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:45
RepositoryIf::MetaData metadata
Definition repositoryIf.ipp:44
DataPointPath link_path
Definition repositoryIf.ipp:126
DataPointPath path
Definition repositoryIf.ipp:125
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:127
DataPointPath path
Definition repositoryIf.ipp:49
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:50
DataPointPath path
Definition repositoryIf.ipp:54
bool & result
Definition repositoryIf.ipp:55
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:56
bool recurse
Definition repositoryIf.ipp:61
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:63
std::pair< RepositoryIf::PathList, RepositoryIf::PathList > & result
Definition repositoryIf.ipp:62
DataPointPath path
Definition repositoryIf.ipp:60
DataPointPath path
Definition repositoryIf.ipp:93
gsl::span< T > data
Definition repositoryIf.ipp:94
RepositoryIf::MetaData input_metadata
Definition repositoryIf.ipp:95
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:98
std::optional< std::reference_wrapper< RepositoryIf::MetaData > > output_metadata
Definition repositoryIf.ipp:96
size_t offset
Definition repositoryIf.ipp:97
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:109
DataPointPath path
Definition repositoryIf.ipp:104
RepositoryIf::MetaData metadata
Definition repositoryIf.ipp:106
gsl::span< const T > data
Definition repositoryIf.ipp:105
size_t offset
Definition repositoryIf.ipp:107
std::optional< std::reference_wrapper< RepositoryIf::MetaData > > output_metadata
Definition repositoryIf.ipp:108
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:115
RepositoryIf::MetaData & metadata
Definition repositoryIf.ipp:114
DataPointPath path
Definition repositoryIf.ipp:113
T ElementType
Definition repositoryIf.ipp:68
std::function< gsl::span< T >(const RepositoryIf::MetaData &)> PrepareFunctionType
Definition repositoryIf.ipp:69
std::optional< std::reference_wrapper< RepositoryIf::MetaData > > metadata
Definition repositoryIf.ipp:76
PrepareFunctionType prepare_buffer
Definition repositoryIf.ipp:75
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:77
DataPointPath path
Definition repositoryIf.ipp:70
DataPointPath path
Definition repositoryIf.ipp:131
DataPointPath link_path
Definition repositoryIf.ipp:132
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:133
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:545
MatrixBuffer< T, A > BufferType
Definition repositoryIf.ipp:544
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:550
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:566
RtcMatrix< ElementType > DataPointType
Definition repositoryIf.ipp:546
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:570
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:547
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:562
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:585
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:602
static gsl::span< ElementType > MakeSpan(BufferType &buffer)=delete
Span not constructable from a MatrixBuffer<bool> type.
boost::container::vector< bool > TempBufferType
Definition repositoryIf.ipp:586
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)=delete
Span not constructable from a MatrixBuffer<bool> type.
static void CopyToTempBuffer(const BufferType &buffer, std::shared_ptr< TempBufferType > &temp_buffer, size_t offset, size_t count)
Definition repositoryIf.ipp:611
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:583
static void CopyFromTempBuffer(BufferType &buffer, const std::shared_ptr< TempBufferType > &temp_buffer, size_t offset, size_t count)
Definition repositoryIf.ipp:620
MatrixBuffer< bool, A > BufferType
Definition repositoryIf.ipp:582
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:588
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:638
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:650
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:658
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:633
MatrixSpan< T > BufferType
Definition repositoryIf.ipp:632
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:635
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:654
RtcMatrix< ElementType > DataPointType
Definition repositoryIf.ipp:634
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:862
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:882
std::remove_cv_t< T > ElementType
Definition repositoryIf.ipp:860
T[N][M] BufferType
Definition repositoryIf.ipp:859
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:865
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:887
RtcMatrix< ElementType > DataPointType
Definition repositoryIf.ipp:861
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:877
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:810
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:790
T[N] BufferType
Definition repositoryIf.ipp:787
void TempBufferType
Definition repositoryIf.ipp:791
RtcVector< ElementType > DataPointType
Definition repositoryIf.ipp:789
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:793
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:814
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:806
std::remove_cv_t< T > ElementType
Definition repositoryIf.ipp:788
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:439
RtcVector< ElementType > DataPointType
Definition repositoryIf.ipp:418
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:443
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:417
boost::container::vector< T, A > BufferType
Definition repositoryIf.ipp:416
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:422
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:435
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:840
RtcString DataPointType
Definition repositoryIf.ipp:828
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:836
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:844
char[N] BufferType
Definition repositoryIf.ipp:826
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:829
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:832
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:478
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:461
gsl::span< T, N > BufferType
Definition repositoryIf.ipp:455
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:456
RtcVector< ElementType > DataPointType
Definition repositoryIf.ipp:457
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:482
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:474
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:458
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:495
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:508
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:504
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:512
gsl::span< char, N > BufferType
Definition repositoryIf.ipp:494
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:497
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:500
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:533
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:537
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:520
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:529
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:525
gsl::span< const char, N > BufferType
Definition repositoryIf.ipp:519
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:673
std::array< T, N > BufferType
Definition repositoryIf.ipp:670
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:697
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:693
RtcVector< ElementType > DataPointType
Definition repositoryIf.ipp:672
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:689
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:676
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:671
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:715
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:712
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:727
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:723
std::array< char, N > BufferType
Definition repositoryIf.ipp:709
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:710
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:719
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:757
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:745
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:769
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:763
std::array< std::array< T, M >, N > BufferType
Definition repositoryIf.ipp:739
std::string BufferType
Definition repositoryIf.ipp:266
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:272
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:276
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:269
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:284
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:280
RtcString DataPointType
Definition repositoryIf.ipp:268
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:267
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:302
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:315
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:299
static gsl::span< ElementType > MakeSpan(BufferType &buffer)=delete
It is not possible to create mutable span from a read-only string view.
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:311
std::string_view BufferType
Definition repositoryIf.ipp:296
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:297
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:328
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:333
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Definition repositoryIf.ipp:346
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:330
RtcVector< ElementType > DataPointType
Definition repositoryIf.ipp:329
std::vector< T, A > BufferType
Definition repositoryIf.ipp:327
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Definition repositoryIf.ipp:350
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:354
static const bool USES_TEMP_BUFFER
Definition repositoryIf.ipp:369
static gsl::span< ElementType > MakeSpan(BufferType &buffer)=delete
Span not constructable from a std::vector<bool> type.
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)=delete
Span not constructable from a std::vector<bool> type.
boost::container::vector< bool > TempBufferType
Definition repositoryIf.ipp:370
static void CopyFromTempBuffer(BufferType &buffer, const std::shared_ptr< TempBufferType > &temp_buffer, size_t offset, size_t count)
Definition repositoryIf.ipp:404
std::remove_cv_t< typename BufferType::value_type > ElementType
Definition repositoryIf.ipp:367
std::vector< bool, A > BufferType
Definition repositoryIf.ipp:366
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Definition repositoryIf.ipp:372
static void CopyToTempBuffer(const BufferType &buffer, std::shared_ptr< TempBufferType > &temp_buffer, size_t offset, size_t count)
Definition repositoryIf.ipp:395
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Definition repositoryIf.ipp:386
void TempBufferType
Defines the temporary buffer type (set to void if USES_TEMP_BUFFER is false).
Definition repositoryIf.ipp:166
static const bool USES_TEMP_BUFFER
Flag indicating if a temporary buffer is required to read/write this type.
Definition repositoryIf.ipp:163
static void CopyToTempBuffer(const BufferType &buffer, std::shared_ptr< TempBufferType > &temp_buffer, size_t offset, size_t count)=delete
Copy data from the original buffer into the temporary buffer.
static gsl::span< const ElementType > MakeSpan(const BufferType &buffer)
Creates a span from a read-only buffer object.
Definition repositoryIf.ipp:201
std::remove_cv_t< T > ElementType
Defines the element type of the buffer object.
Definition repositoryIf.ipp:157
T DataPointType
Defines the corresponding data point type that type T is compatible with.
Definition repositoryIf.ipp:160
static gsl::span< ElementType > MakeSpan(BufferType &buffer)
Creates a span from a buffer object.
Definition repositoryIf.ipp:192
static RtcVectorUInt64 GetShape(const BufferType &buffer)
Returns the shape of a buffer object.
Definition repositoryIf.ipp:175
T BufferType
Defines the type of the buffer object that handles type T.
Definition repositoryIf.ipp:154
static bool ResizeBuffer(BufferType &buffer, const RtcVectorUInt64 &shape)
Tries to resize the buffer to the given shape.
Definition repositoryIf.ipp:218
static void CopyFromTempBuffer(BufferType &buffer, const std::shared_ptr< TempBufferType > &temp_buffer, size_t offset, size_t count)=delete
Copy data from the temporary buffer into the original buffer.
DataPointPath path
Definition repositoryIf.ipp:119
RepositoryIf::MetaData metadata
Definition repositoryIf.ipp:120
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:121
RepositoryIf::MetaData metadata
Definition repositoryIf.ipp:85
DataPointPath path
Definition repositoryIf.ipp:83
gsl::span< const T > data
Definition repositoryIf.ipp:84
std::optional< std::reference_wrapper< RepositoryIf::MetaData > > output_metadata
Definition repositoryIf.ipp:86
T ElementType
Definition repositoryIf.ipp:82
RepositoryIf::CallbackType callback
Definition repositoryIf.ipp:87
Provides useful mechanisms to test various type traits.