Add CTF IR classes specific to `src.ctf.*`
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 21 May 2024 17:33:14 +0000 (13:33 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Wed, 4 Sep 2024 19:05:14 +0000 (15:05 -0400)
This patch uses the `ctf::ir` API to expose a source-specific CTF IR API
under the `ctf::src` namespace, to be used by both the `src.ctf.fs` and
the `src.ctf.lttng-live` component classes.

This specific CTF IR API augments the common `ctf::ir` API with user
mixins to add the following:

• Any field class has a "deep type".

  See the comment of `ctf::src::FcDeepType` to understand why we need
  such an enumeration.

• The field class, clock class, event record class, data stream class,
  and trace class classes have an optional equivalent libbabeltrace2
  class object.

  This is a bridge between the CTF IR world and the libbabeltrace2 world
  to be able to create corresponding libbabeltrace2 messages when
  decoding a data stream with the CTF IR classes.

  If a field class has no equivalent libbabeltrace2 class, then the
  values of its instances aren't transported through messages as
  field objects.

• A clock class object may hold its equivalent libbabeltrace2 class
  (owned, shared reference).

• A trace class object may hold its equivalent libbabeltrace2 class
  (owned, shared reference).

• Boolean and integer field classes have an optional "key value"
  saving index.

  See the comment of the `ctf::src::KeyValSavingIndexes` alias to
  learn more.

• Dynamic-length, optional, and variant field classes have a saved
  key value index.

  Again, see the comment of `ctf::src::KeyValSavingIndexes` to
  learn more.

• Field class and field location mixins have an optional text
  location member.

  This will help with precise metadata stream error reporting.

• A trace class contains the maximum number of saved key values for
  its instance.

  Once more, see the comment of `ctf::src::KeyValSavingIndexes` to
  learn more.

The new API adds templateless aliases for all the configurable CTF IR
types, for example `src::ctf::FixedLenIntFc`.

The new API also offers user mixin agnostic functions to create all its
CTF IR objects. For example, call ctf::src::createDynLenBlobFc() to
create a `ctf::src` dynamic-length BLOB field class.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: I854d5562778e05f4c438a4e937758bbce114f951
Reviewed-on: https://review.lttng.org/c/babeltrace/+/7840
Reviewed-on: https://review.lttng.org/c/babeltrace/+/12255
Tested-by: jenkins <jenkins@lttng.org>
CI-Build: Simon Marchi <simon.marchi@efficios.com>

src/Makefile.am
src/plugins/ctf/common/metadata/ctf-ir.hpp
src/plugins/ctf/common/src/metadata/ctf-ir.cpp [new file with mode: 0644]
src/plugins/ctf/common/src/metadata/ctf-ir.hpp [new file with mode: 0644]

index a21b7189e1e58a8243bcaa5046a4bb1069ab8c72..fc5d270954c72ced1fbd80d39bfdf81f2df7d2cf 100644 (file)
@@ -685,6 +685,8 @@ plugins_ctf_babeltrace_plugin_ctf_la_SOURCES = \
        plugins/ctf/common/src/bfcr/bfcr.cpp \
        plugins/ctf/common/src/bfcr/bfcr.hpp \
        plugins/ctf/common/src/clk-cls-cfg.hpp \
+       plugins/ctf/common/src/metadata/ctf-ir.cpp \
+       plugins/ctf/common/src/metadata/ctf-ir.hpp \
        plugins/ctf/common/src/msg-iter/msg-iter.cpp \
        plugins/ctf/common/src/msg-iter/msg-iter.hpp \
        plugins/ctf/fs-sink/fs-sink.cpp \
index 17073f6c7da3e539e4f6ea27ef51741ac811322e..aad3d63a6518ab39d706c81e7c9e79d971d4273a 100644 (file)
@@ -1026,7 +1026,7 @@ public:
     /*
      * Length of instances of this field class.
      */
-    const bt2c::DataLen len() const noexcept
+    bt2c::DataLen len() const noexcept
     {
         return _mLen;
     }
diff --git a/src/plugins/ctf/common/src/metadata/ctf-ir.cpp b/src/plugins/ctf/common/src/metadata/ctf-ir.cpp
new file mode 100644 (file)
index 0000000..6b52ff8
--- /dev/null
@@ -0,0 +1,878 @@
+/*
+ * Copyright (c) 2022 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "cpp-common/bt2c/call.hpp"
+#include "cpp-common/bt2s/make-unique.hpp"
+
+#include "ctf-ir.hpp"
+
+namespace ctf {
+namespace src {
+namespace internal {
+
+void DependentFcMixin::keyFcs(FcSet keyFcs)
+{
+    _mKeyFcs = std::move(keyFcs);
+}
+
+FieldLocMixin::FieldLocMixin(const bt2c::TextLoc& loc) noexcept : _mLoc {loc}
+{
+}
+
+FcMixin::FcMixin(const bt2c::TextLoc& loc) noexcept : _mLoc {loc}
+{
+}
+
+FcMixin::FcMixin(const FcDeepType deepType, const bt2c::TextLoc& loc) noexcept :
+    _mDeepType {deepType}, _mLoc {loc}
+{
+}
+
+void ClkClsMixin::sharedLibCls(bt2::ClockClass::Shared cls) noexcept
+{
+    static_cast<ir::ClkCls<CtfIrMixins>&>(*this).libCls(*cls);
+    _mSharedLibCls = std::move(cls);
+}
+
+void TraceClsMixin::sharedLibCls(bt2::TraceClass::Shared cls) noexcept
+{
+    static_cast<ir::TraceCls<CtfIrMixins>&>(*this).libCls(*cls);
+    _mSharedLibCls = std::move(cls);
+}
+
+} /* namespace internal */
+
+namespace {
+
+bool isStdBitArrayFc(const unsigned int align, const bt2c::DataLen len) noexcept
+{
+    return align % 8 == 0 && (*len == 8 || *len == 16 || *len == 32 || *len == 64);
+}
+
+} /* namespace */
+
+FieldLoc createFieldLoc(const bt2c::TextLoc& loc, bt2s::optional<Scope> origin,
+                        FieldLoc::Items items)
+{
+    return FieldLoc {internal::CtfIrMixins::FieldLoc {loc}, std::move(origin), std::move(items)};
+}
+
+std::unique_ptr<FixedLenBitArrayFc>
+createFixedLenBitArrayFc(const bt2c::TextLoc& loc, const unsigned int align,
+                         const bt2c::DataLen len, const ByteOrder byteOrder,
+                         const bt2s::optional<BitOrder>& bitOrder, OptAttrs attrs)
+{
+    const auto deepType = bt2c::call([align, len, byteOrder, &bitOrder] {
+        const auto isRev = FixedLenBitArrayFc::isRev(byteOrder, bitOrder);
+        const auto isStd = isStdBitArrayFc(align, len);
+
+        if (byteOrder == ByteOrder::Big) {
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBitArrayBa8Rev;
+                    case 16:
+                        return FcDeepType::FixedLenBitArrayBa16BeRev;
+                    case 32:
+                        return FcDeepType::FixedLenBitArrayBa32BeRev;
+                    case 64:
+                        return FcDeepType::FixedLenBitArrayBa64BeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBitArrayBa8;
+                    case 16:
+                        return FcDeepType::FixedLenBitArrayBa16Be;
+                    case 32:
+                        return FcDeepType::FixedLenBitArrayBa32Be;
+                    case 64:
+                        return FcDeepType::FixedLenBitArrayBa64Be;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return FcDeepType::FixedLenBitArrayBeRev;
+                } else {
+                    return FcDeepType::FixedLenBitArrayBe;
+                }
+            }
+        } else {
+            /* Little-endian */
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBitArrayBa8Rev;
+                    case 16:
+                        return FcDeepType::FixedLenBitArrayBa16LeRev;
+                    case 32:
+                        return FcDeepType::FixedLenBitArrayBa32LeRev;
+                    case 64:
+                        return FcDeepType::FixedLenBitArrayBa64LeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBitArrayBa8;
+                    case 16:
+                        return FcDeepType::FixedLenBitArrayBa16Le;
+                    case 32:
+                        return FcDeepType::FixedLenBitArrayBa32Le;
+                    case 64:
+                        return FcDeepType::FixedLenBitArrayBa64Le;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return FcDeepType::FixedLenBitArrayLeRev;
+                } else {
+                    return FcDeepType::FixedLenBitArrayLe;
+                }
+            }
+        }
+    });
+
+    return bt2s::make_unique<FixedLenBitArrayFc>(internal::CtfIrMixins::Fc {deepType, loc},
+                                                 internal::CtfIrMixins::FixedLenBitArrayFc {},
+                                                 align, len, byteOrder, bitOrder, std::move(attrs));
+}
+
+std::unique_ptr<FixedLenBitMapFc>
+createFixedLenBitMapFc(const bt2c::TextLoc& loc, const unsigned int align, const bt2c::DataLen len,
+                       const ByteOrder byteOrder, FixedLenBitMapFc::Flags flags,
+                       const bt2s::optional<BitOrder>& bitOrder, OptAttrs attrs)
+{
+    const auto deepType = bt2c::call([align, len, byteOrder, &bitOrder] {
+        const auto isRev = FixedLenBitArrayFc::isRev(byteOrder, bitOrder);
+        const auto isStd = isStdBitArrayFc(align, len);
+
+        if (byteOrder == ByteOrder::Big) {
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBitMapBa8Rev;
+                    case 16:
+                        return FcDeepType::FixedLenBitMapBa16BeRev;
+                    case 32:
+                        return FcDeepType::FixedLenBitMapBa32BeRev;
+                    case 64:
+                        return FcDeepType::FixedLenBitMapBa64BeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBitMapBa8;
+                    case 16:
+                        return FcDeepType::FixedLenBitMapBa16Be;
+                    case 32:
+                        return FcDeepType::FixedLenBitMapBa32Be;
+                    case 64:
+                        return FcDeepType::FixedLenBitMapBa64Be;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return FcDeepType::FixedLenBitMapBeRev;
+                } else {
+                    return FcDeepType::FixedLenBitMapBe;
+                }
+            }
+        } else {
+            /* Little-endian */
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBitMapBa8Rev;
+                    case 16:
+                        return FcDeepType::FixedLenBitMapBa16LeRev;
+                    case 32:
+                        return FcDeepType::FixedLenBitMapBa32LeRev;
+                    case 64:
+                        return FcDeepType::FixedLenBitMapBa64LeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBitMapBa8;
+                    case 16:
+                        return FcDeepType::FixedLenBitMapBa16Le;
+                    case 32:
+                        return FcDeepType::FixedLenBitMapBa32Le;
+                    case 64:
+                        return FcDeepType::FixedLenBitMapBa64Le;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return FcDeepType::FixedLenBitMapLeRev;
+                } else {
+                    return FcDeepType::FixedLenBitMapLe;
+                }
+            }
+        }
+    });
+
+    return bt2s::make_unique<FixedLenBitMapFc>(
+        internal::CtfIrMixins::Fc {deepType, loc}, internal::CtfIrMixins::FixedLenBitArrayFc {},
+        internal::CtfIrMixins::FixedLenBitMapFc {}, align, len, byteOrder, std::move(flags),
+        bitOrder, std::move(attrs));
+}
+
+std::unique_ptr<FixedLenBoolFc>
+createFixedLenBoolFc(const bt2c::TextLoc& loc, const unsigned int align, const bt2c::DataLen len,
+                     const ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder,
+                     OptAttrs attrs)
+{
+    const auto deepType = bt2c::call([align, len, byteOrder, &bitOrder] {
+        const auto isRev = FixedLenBitArrayFc::isRev(byteOrder, bitOrder);
+        const auto isStd = isStdBitArrayFc(align, len);
+
+        if (byteOrder == ByteOrder::Big) {
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBoolBa8Rev;
+                    case 16:
+                        return FcDeepType::FixedLenBoolBa16BeRev;
+                    case 32:
+                        return FcDeepType::FixedLenBoolBa32BeRev;
+                    case 64:
+                        return FcDeepType::FixedLenBoolBa64BeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBoolBa8;
+                    case 16:
+                        return FcDeepType::FixedLenBoolBa16Be;
+                    case 32:
+                        return FcDeepType::FixedLenBoolBa32Be;
+                    case 64:
+                        return FcDeepType::FixedLenBoolBa64Be;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return FcDeepType::FixedLenBoolBeRev;
+                } else {
+                    return FcDeepType::FixedLenBoolBe;
+                }
+            }
+        } else {
+            /* Little-endian */
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBoolBa8Rev;
+                    case 16:
+                        return FcDeepType::FixedLenBoolBa16LeRev;
+                    case 32:
+                        return FcDeepType::FixedLenBoolBa32LeRev;
+                    case 64:
+                        return FcDeepType::FixedLenBoolBa64LeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenBoolBa8;
+                    case 16:
+                        return FcDeepType::FixedLenBoolBa16Le;
+                    case 32:
+                        return FcDeepType::FixedLenBoolBa32Le;
+                    case 64:
+                        return FcDeepType::FixedLenBoolBa64Le;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return FcDeepType::FixedLenBoolLeRev;
+                } else {
+                    return FcDeepType::FixedLenBoolLe;
+                }
+            }
+        }
+    });
+
+    return bt2s::make_unique<FixedLenBoolFc>(internal::CtfIrMixins::Fc {deepType, loc},
+                                             internal::CtfIrMixins::FixedLenBitArrayFc {},
+                                             internal::CtfIrMixins::FixedLenBoolFc {}, align, len,
+                                             byteOrder, bitOrder, std::move(attrs));
+}
+
+std::unique_ptr<FixedLenFloatFc>
+createFixedLenFloatFc(const bt2c::TextLoc& loc, const unsigned int align, const bt2c::DataLen len,
+                      const ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder,
+                      OptAttrs attrs)
+{
+    const auto deepType = bt2c::call([align, len, byteOrder, &bitOrder] {
+        const auto isRev = FixedLenBitArrayFc::isRev(byteOrder, bitOrder);
+        const auto isStd = isStdBitArrayFc(align, len);
+
+        if (byteOrder == ByteOrder::Big) {
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 32:
+                        return FcDeepType::FixedLenFloatBa32BeRev;
+                    case 64:
+                        return FcDeepType::FixedLenFloatBa64BeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 32:
+                        return FcDeepType::FixedLenFloatBa32Be;
+                    case 64:
+                        return FcDeepType::FixedLenFloatBa64Be;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    switch (*len) {
+                    case 32:
+                        return FcDeepType::FixedLenFloat32BeRev;
+                    case 64:
+                        return FcDeepType::FixedLenFloat64BeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 32:
+                        return FcDeepType::FixedLenFloat32Be;
+                    case 64:
+                        return FcDeepType::FixedLenFloat64Be;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            }
+        } else {
+            /* Little-endian */
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 32:
+                        return FcDeepType::FixedLenFloatBa32LeRev;
+                    case 64:
+                        return FcDeepType::FixedLenFloatBa64LeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 32:
+                        return FcDeepType::FixedLenFloatBa32Le;
+                    case 64:
+                        return FcDeepType::FixedLenFloatBa64Le;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    switch (*len) {
+                    case 32:
+                        return FcDeepType::FixedLenFloat32LeRev;
+                    case 64:
+                        return FcDeepType::FixedLenFloat64LeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 32:
+                        return FcDeepType::FixedLenFloat32Le;
+                    case 64:
+                        return FcDeepType::FixedLenFloat64Le;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            }
+        }
+    });
+
+    return bt2s::make_unique<FixedLenFloatFc>(internal::CtfIrMixins::Fc {deepType, loc},
+                                              internal::CtfIrMixins::FixedLenBitArrayFc {}, align,
+                                              len, byteOrder, bitOrder, std::move(attrs));
+}
+
+std::unique_ptr<FixedLenUIntFc>
+createFixedLenUIntFc(const bt2c::TextLoc& loc, const unsigned int align, const bt2c::DataLen len,
+                     const ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder,
+                     const DispBase prefDispBase, FixedLenUIntFc::Mappings mappings,
+                     UIntFieldRoles roles, OptAttrs attrs)
+{
+    const auto deepType = bt2c::call([align, len, byteOrder, &bitOrder, &roles] {
+        const auto isRev = FixedLenBitArrayFc::isRev(byteOrder, bitOrder);
+        const auto isStd = isStdBitArrayFc(align, len);
+        const auto hasRole = !roles.empty();
+
+        if (byteOrder == ByteOrder::Big) {
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return hasRole ? FcDeepType::FixedLenUIntBa8RevWithRole :
+                                         FcDeepType::FixedLenUIntBa8Rev;
+                    case 16:
+                        return hasRole ? FcDeepType::FixedLenUIntBa16BeRevWithRole :
+                                         FcDeepType::FixedLenUIntBa16BeRev;
+                    case 32:
+                        return hasRole ? FcDeepType::FixedLenUIntBa32BeRevWithRole :
+                                         FcDeepType::FixedLenUIntBa32BeRev;
+                    case 64:
+                        return hasRole ? FcDeepType::FixedLenUIntBa64BeRevWithRole :
+                                         FcDeepType::FixedLenUIntBa64BeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return hasRole ? FcDeepType::FixedLenUIntBa8WithRole :
+                                         FcDeepType::FixedLenUIntBa8;
+                    case 16:
+                        return hasRole ? FcDeepType::FixedLenUIntBa16BeWithRole :
+                                         FcDeepType::FixedLenUIntBa16Be;
+                    case 32:
+                        return hasRole ? FcDeepType::FixedLenUIntBa32BeWithRole :
+                                         FcDeepType::FixedLenUIntBa32Be;
+                    case 64:
+                        return hasRole ? FcDeepType::FixedLenUIntBa64BeWithRole :
+                                         FcDeepType::FixedLenUIntBa64Be;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return hasRole ? FcDeepType::FixedLenUIntBeRevWithRole :
+                                     FcDeepType::FixedLenUIntBeRev;
+                } else {
+                    return hasRole ? FcDeepType::FixedLenUIntBeWithRole :
+                                     FcDeepType::FixedLenUIntBe;
+                }
+            }
+        } else {
+            /* Little-endian */
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return hasRole ? FcDeepType::FixedLenUIntBa8RevWithRole :
+                                         FcDeepType::FixedLenUIntBa8Rev;
+                    case 16:
+                        return hasRole ? FcDeepType::FixedLenUIntBa16LeRevWithRole :
+                                         FcDeepType::FixedLenUIntBa16LeRev;
+                    case 32:
+                        return hasRole ? FcDeepType::FixedLenUIntBa32LeRevWithRole :
+                                         FcDeepType::FixedLenUIntBa32LeRev;
+                    case 64:
+                        return hasRole ? FcDeepType::FixedLenUIntBa64LeRevWithRole :
+                                         FcDeepType::FixedLenUIntBa64LeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return hasRole ? FcDeepType::FixedLenUIntBa8WithRole :
+                                         FcDeepType::FixedLenUIntBa8;
+                    case 16:
+                        return hasRole ? FcDeepType::FixedLenUIntBa16LeWithRole :
+                                         FcDeepType::FixedLenUIntBa16Le;
+                    case 32:
+                        return hasRole ? FcDeepType::FixedLenUIntBa32LeWithRole :
+                                         FcDeepType::FixedLenUIntBa32Le;
+                    case 64:
+                        return hasRole ? FcDeepType::FixedLenUIntBa64LeWithRole :
+                                         FcDeepType::FixedLenUIntBa64Le;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return hasRole ? FcDeepType::FixedLenUIntLeRevWithRole :
+                                     FcDeepType::FixedLenUIntLeRev;
+                } else {
+                    return hasRole ? FcDeepType::FixedLenUIntLeWithRole :
+                                     FcDeepType::FixedLenUIntLe;
+                }
+            }
+        }
+    });
+
+    return bt2s::make_unique<FixedLenUIntFc>(
+        internal::CtfIrMixins::Fc {deepType, loc}, internal::CtfIrMixins::FixedLenBitArrayFc {},
+        internal::CtfIrMixins::FixedLenIntFc {}, internal::CtfIrMixins::FixedLenUIntFc {}, align,
+        len, byteOrder, bitOrder, prefDispBase, std::move(mappings), std::move(roles),
+        std::move(attrs));
+}
+
+std::unique_ptr<FixedLenSIntFc>
+createFixedLenSIntFc(const bt2c::TextLoc& loc, const unsigned int align, const bt2c::DataLen len,
+                     const ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder,
+                     const DispBase prefDispBase, FixedLenSIntFc::Mappings mappings, OptAttrs attrs)
+{
+    const auto deepType = bt2c::call([align, len, byteOrder, &bitOrder] {
+        const auto isRev = FixedLenBitArrayFc::isRev(byteOrder, bitOrder);
+        const auto isStd = isStdBitArrayFc(align, len);
+
+        if (byteOrder == ByteOrder::Big) {
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenSIntBa8Rev;
+                    case 16:
+                        return FcDeepType::FixedLenSIntBa16BeRev;
+                    case 32:
+                        return FcDeepType::FixedLenSIntBa32BeRev;
+                    case 64:
+                        return FcDeepType::FixedLenSIntBa64BeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenSIntBa8;
+                    case 16:
+                        return FcDeepType::FixedLenSIntBa16Be;
+                    case 32:
+                        return FcDeepType::FixedLenSIntBa32Be;
+                    case 64:
+                        return FcDeepType::FixedLenSIntBa64Be;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return FcDeepType::FixedLenSIntBeRev;
+                } else {
+                    return FcDeepType::FixedLenSIntBe;
+                }
+            }
+        } else {
+            /* Little-endian */
+            if (isStd) {
+                if (isRev) {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenSIntBa8Rev;
+                    case 16:
+                        return FcDeepType::FixedLenSIntBa16LeRev;
+                    case 32:
+                        return FcDeepType::FixedLenSIntBa32LeRev;
+                    case 64:
+                        return FcDeepType::FixedLenSIntBa64LeRev;
+                    default:
+                        bt_common_abort();
+                    }
+                } else {
+                    switch (*len) {
+                    case 8:
+                        return FcDeepType::FixedLenSIntBa8;
+                    case 16:
+                        return FcDeepType::FixedLenSIntBa16Le;
+                    case 32:
+                        return FcDeepType::FixedLenSIntBa32Le;
+                    case 64:
+                        return FcDeepType::FixedLenSIntBa64Le;
+                    default:
+                        bt_common_abort();
+                    }
+                }
+            } else {
+                if (isRev) {
+                    return FcDeepType::FixedLenSIntLeRev;
+                } else {
+                    return FcDeepType::FixedLenSIntLe;
+                }
+            }
+        }
+    });
+
+    return bt2s::make_unique<FixedLenSIntFc>(
+        internal::CtfIrMixins::Fc {deepType, loc}, internal::CtfIrMixins::FixedLenBitArrayFc {},
+        internal::CtfIrMixins::FixedLenIntFc {}, align, len, byteOrder, bitOrder, prefDispBase,
+        std::move(mappings), std::move(attrs));
+}
+
+std::unique_ptr<VarLenUIntFc> createVarLenUIntFc(const bt2c::TextLoc& loc,
+                                                 const DispBase prefDispBase,
+                                                 VarLenUIntFc::Mappings mappings,
+                                                 UIntFieldRoles roles, OptAttrs attrs)
+{
+    const auto deepType = roles.empty() ? FcDeepType::VarLenUInt : FcDeepType::VarLenUIntWithRole;
+
+    return bt2s::make_unique<VarLenUIntFc>(internal::CtfIrMixins::Fc {deepType, loc},
+                                           internal::CtfIrMixins::VarLenIntFc {},
+                                           internal::CtfIrMixins::VarLenUIntFc {}, prefDispBase,
+                                           std::move(mappings), std::move(roles), std::move(attrs));
+}
+
+std::unique_ptr<VarLenSIntFc> createVarLenSIntFc(const bt2c::TextLoc& loc,
+                                                 const DispBase prefDispBase,
+                                                 VarLenSIntFc::Mappings mappings, OptAttrs attrs)
+{
+    return bt2s::make_unique<VarLenSIntFc>(internal::CtfIrMixins::Fc {FcDeepType::VarLenSInt, loc},
+                                           internal::CtfIrMixins::VarLenIntFc {}, prefDispBase,
+                                           std::move(mappings), std::move(attrs));
+}
+
+std::unique_ptr<NullTerminatedStrFc>
+createNullTerminatedStrFc(const bt2c::TextLoc& loc, const StrEncoding encoding, OptAttrs attrs)
+{
+    const auto deepType = bt2c::call([encoding] {
+        switch (encoding) {
+        case StrEncoding::Utf8:
+            return FcDeepType::NullTerminatedStrUtf8;
+        case StrEncoding::Utf16Be:
+        case StrEncoding::Utf16Le:
+            return FcDeepType::NullTerminatedStrUtf16;
+        case StrEncoding::Utf32Be:
+        case StrEncoding::Utf32Le:
+            return FcDeepType::NullTerminatedStrUtf32;
+        default:
+            bt_common_abort();
+        }
+    });
+
+    return bt2s::make_unique<NullTerminatedStrFc>(internal::CtfIrMixins::Fc {deepType, loc},
+                                                  encoding, std::move(attrs));
+}
+
+std::unique_ptr<StaticLenStrFc> createStaticLenStrFc(const bt2c::TextLoc& loc,
+                                                     const std::size_t len,
+                                                     const StrEncoding encoding, OptAttrs attrs)
+{
+    return bt2s::make_unique<StaticLenStrFc>(
+        internal::CtfIrMixins::Fc {FcDeepType::StaticLenStr, loc},
+        internal::CtfIrMixins::StaticLenStrFc {}, len, encoding, std::move(attrs));
+}
+
+std::unique_ptr<DynLenStrFc> createDynLenStrFc(const bt2c::TextLoc& loc, FieldLoc lenFieldLoc,
+                                               const StrEncoding encoding, OptAttrs attrs)
+{
+    return bt2s::make_unique<DynLenStrFc>(internal::CtfIrMixins::Fc {FcDeepType::DynLenStr, loc},
+                                          internal::CtfIrMixins::DynLenStrFc {},
+                                          std::move(lenFieldLoc), encoding, std::move(attrs));
+}
+
+std::unique_ptr<StaticLenBlobFc> createStaticLenBlobFc(const bt2c::TextLoc& loc,
+                                                       const std::size_t len, std::string mediaType,
+                                                       const bool hasMetadataStreamUuidRole,
+                                                       OptAttrs attrs)
+{
+    const auto deepType = hasMetadataStreamUuidRole ?
+                              FcDeepType::StaticLenBlobWithMetadataStreamUuidRole :
+                              FcDeepType::StaticLenBlob;
+
+    return bt2s::make_unique<StaticLenBlobFc>(
+        internal::CtfIrMixins::Fc {deepType, loc}, internal::CtfIrMixins::StaticLenBlobFc {}, len,
+        std::move(mediaType), hasMetadataStreamUuidRole, std::move(attrs));
+}
+
+std::unique_ptr<DynLenBlobFc> createDynLenBlobFc(const bt2c::TextLoc& loc, FieldLoc lenFieldLoc,
+                                                 std::string mediaType, OptAttrs attrs)
+{
+    return bt2s::make_unique<DynLenBlobFc>(internal::CtfIrMixins::Fc {FcDeepType::DynLenBlob, loc},
+                                           internal::CtfIrMixins::DynLenBlobFc {},
+                                           std::move(lenFieldLoc), std::move(mediaType),
+                                           std::move(attrs));
+}
+
+std::unique_ptr<StaticLenArrayFc> createStaticLenArrayFc(const bt2c::TextLoc& loc,
+                                                         const std::size_t len, Fc::UP elemFc,
+                                                         const unsigned int minAlign,
+                                                         const bool hasMetadataStreamUuidRole,
+                                                         OptAttrs attrs)
+{
+    const auto deepType = hasMetadataStreamUuidRole ?
+                              FcDeepType::StaticLenArrayWithMetadataStreamUuidRole :
+                              FcDeepType::StaticLenArray;
+
+    return bt2s::make_unique<StaticLenArrayFc>(internal::CtfIrMixins::Fc {deepType, loc},
+                                               internal::CtfIrMixins::StaticLenArrayFc {}, len,
+                                               std::move(elemFc), minAlign, std::move(attrs));
+}
+
+std::unique_ptr<DynLenArrayFc> createDynLenArrayFc(const bt2c::TextLoc& loc, FieldLoc lenFieldLoc,
+                                                   Fc::UP elemFc, const unsigned int minAlign,
+                                                   OptAttrs attrs)
+{
+    return bt2s::make_unique<DynLenArrayFc>(
+        internal::CtfIrMixins::Fc {FcDeepType::DynLenArray, loc},
+        internal::CtfIrMixins::DynLenArrayFc {}, std::move(lenFieldLoc), std::move(elemFc),
+        minAlign, std::move(attrs));
+}
+
+StructFieldMemberCls createStructFieldMemberCls(std::string name, Fc::UP fc, OptAttrs attrs)
+{
+    return StructFieldMemberCls {internal::CtfIrMixins::StructFieldMemberCls {}, std::move(name),
+                                 std::move(fc), std::move(attrs)};
+}
+
+std::unique_ptr<StructFc> createStructFc(const bt2c::TextLoc& loc,
+                                         StructFc::MemberClasses&& memberClasses,
+                                         const unsigned int minAlign, OptAttrs attrs)
+{
+    return bt2s::make_unique<StructFc>(internal::CtfIrMixins::Fc {FcDeepType::Struct, loc},
+                                       internal::CtfIrMixins::StructFc {}, std::move(memberClasses),
+                                       minAlign, std::move(attrs));
+}
+
+std::unique_ptr<OptionalWithBoolSelFc> createOptionalFc(const bt2c::TextLoc& loc, Fc::UP fc,
+                                                        FieldLoc selFieldLoc, OptAttrs attrs)
+{
+    return bt2s::make_unique<OptionalWithBoolSelFc>(
+        internal::CtfIrMixins::Fc {FcDeepType::OptionalWithBoolSel, loc},
+        internal::CtfIrMixins::OptionalFc {}, internal::CtfIrMixins::OptionalWithBoolSelFc {},
+        std::move(fc), std::move(selFieldLoc), std::move(attrs));
+}
+
+std::unique_ptr<OptionalWithUIntSelFc> createOptionalFc(const bt2c::TextLoc& loc, Fc::UP fc,
+                                                        FieldLoc selFieldLoc,
+                                                        UIntRangeSet selFieldRanges, OptAttrs attrs)
+{
+    return bt2s::make_unique<OptionalWithUIntSelFc>(
+        internal::CtfIrMixins::Fc {FcDeepType::OptionalWithUIntSel, loc},
+        internal::CtfIrMixins::OptionalFc {}, internal::CtfIrMixins::OptionalWithIntSelFc {},
+        internal::CtfIrMixins::OptionalWithUIntSelFc {}, std::move(fc), std::move(selFieldLoc),
+        std::move(selFieldRanges), std::move(attrs));
+}
+
+std::unique_ptr<OptionalWithSIntSelFc> createOptionalFc(const bt2c::TextLoc& loc, Fc::UP fc,
+                                                        FieldLoc selFieldLoc,
+                                                        SIntRangeSet selFieldRanges, OptAttrs attrs)
+{
+    return bt2s::make_unique<OptionalWithSIntSelFc>(
+        internal::CtfIrMixins::Fc {FcDeepType::OptionalWithSIntSel, loc},
+        internal::CtfIrMixins::OptionalFc {}, internal::CtfIrMixins::OptionalWithIntSelFc {},
+        internal::CtfIrMixins::OptionalWithSIntSelFc {}, std::move(fc), std::move(selFieldLoc),
+        std::move(selFieldRanges), std::move(attrs));
+}
+
+VariantWithUIntSelFc::Opt createVariantFcOpt(Fc::UP fc, UIntRangeSet selFieldRanges,
+                                             bt2s::optional<std::string> name, OptAttrs attrs)
+{
+    return VariantWithUIntSelFc::Opt {internal::CtfIrMixins::VariantFcOpt {}, std::move(fc),
+                                      std::move(selFieldRanges), std::move(name), std::move(attrs)};
+}
+
+VariantWithSIntSelFc::Opt createVariantFcOpt(Fc::UP fc, SIntRangeSet selFieldRanges,
+                                             bt2s::optional<std::string> name, OptAttrs attrs)
+{
+    return VariantWithSIntSelFc::Opt {internal::CtfIrMixins::VariantFcOpt {}, std::move(fc),
+                                      std::move(selFieldRanges), std::move(name), std::move(attrs)};
+}
+
+std::unique_ptr<VariantWithUIntSelFc> createVariantFc(const bt2c::TextLoc& loc,
+                                                      VariantWithUIntSelFc::Opts&& opts,
+                                                      FieldLoc selFieldLoc, OptAttrs attrs)
+{
+    return bt2s::make_unique<VariantWithUIntSelFc>(
+        internal::CtfIrMixins::Fc {FcDeepType::VariantWithUIntSel, loc},
+        internal::CtfIrMixins::VariantFc {}, internal::CtfIrMixins::VariantWithUIntSelFc {},
+        std::move(opts), std::move(selFieldLoc), std::move(attrs));
+}
+
+std::unique_ptr<VariantWithSIntSelFc> createVariantFc(const bt2c::TextLoc& loc,
+                                                      VariantWithSIntSelFc::Opts&& opts,
+                                                      FieldLoc selFieldLoc, OptAttrs attrs)
+{
+    return bt2s::make_unique<VariantWithSIntSelFc>(
+        internal::CtfIrMixins::Fc {FcDeepType::VariantWithSIntSel, loc},
+        internal::CtfIrMixins::VariantFc {}, internal::CtfIrMixins::VariantWithSIntSelFc {},
+        std::move(opts), std::move(selFieldLoc), std::move(attrs));
+}
+
+ClkCls::SP createClkCls(std::string id, const unsigned long long freq,
+                        bt2s::optional<std::string> ns, bt2s::optional<std::string> name,
+                        bt2s::optional<std::string> uid, const ClkOffset& offset,
+                        bt2s::optional<ClkOrigin> origin, bt2s::optional<std::string> descr,
+                        bt2s::optional<unsigned long long> precision,
+                        bt2s::optional<unsigned long long> accuracy, OptAttrs attrs)
+{
+    return std::make_shared<ClkCls>(internal::CtfIrMixins::ClkCls {}, std::move(id), freq,
+                                    std::move(ns), std::move(name), std::move(uid), offset,
+                                    std::move(origin), std::move(descr), std::move(precision),
+                                    std::move(accuracy), std::move(attrs));
+}
+
+std::unique_ptr<EventRecordCls>
+createEventRecordCls(const unsigned long long id, bt2s::optional<std::string> ns,
+                     bt2s::optional<std::string> name, bt2s::optional<std::string> uid,
+                     Fc::UP specCtxFc, Fc::UP payloadFc, OptAttrs attrs)
+{
+    return bt2s::make_unique<EventRecordCls>(
+        internal::CtfIrMixins::EventRecordCls {}, id, std::move(ns), std::move(name),
+        std::move(uid), std::move(specCtxFc), std::move(payloadFc), std::move(attrs));
+}
+
+std::unique_ptr<DataStreamCls>
+createDataStreamCls(const unsigned long long id, bt2s::optional<std::string> ns,
+                    bt2s::optional<std::string> name, bt2s::optional<std::string> uid,
+                    Fc::UP pktCtxFc, Fc::UP eventRecordHeaderFc, Fc::UP commonEventRecordCtxFc,
+                    ClkCls::SP defClkCls, OptAttrs attrs)
+{
+    return bt2s::make_unique<DataStreamCls>(
+        internal::CtfIrMixins::DataStreamCls {}, id, std::move(ns), std::move(name), std::move(uid),
+        std::move(pktCtxFc), std::move(eventRecordHeaderFc), std::move(commonEventRecordCtxFc),
+        std::move(defClkCls), std::move(attrs));
+}
+
+std::unique_ptr<TraceCls> createTraceCls(bt2s::optional<std::string> ns,
+                                         bt2s::optional<std::string> name,
+                                         bt2s::optional<std::string> uid,
+                                         bt2::ConstMapValue::Shared env, Fc::UP pktHeaderFc,
+                                         OptAttrs attrs)
+{
+    return bt2s::make_unique<TraceCls>(internal::CtfIrMixins::TraceCls {}, std::move(ns),
+                                       std::move(name), std::move(uid), std::move(env),
+                                       std::move(pktHeaderFc), std::move(attrs));
+}
+
+} /* namespace src */
+} /* namespace ctf */
diff --git a/src/plugins/ctf/common/src/metadata/ctf-ir.hpp b/src/plugins/ctf/common/src/metadata/ctf-ir.hpp
new file mode 100644 (file)
index 0000000..c202fa9
--- /dev/null
@@ -0,0 +1,1320 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright 2022-2024 Philippe Proulx <pproulx@efficios.com>
+ */
+
+#ifndef BABELTRACE_PLUGINS_CTF_COMMON_SRC_METADATA_CTF_IR_HPP
+#define BABELTRACE_PLUGINS_CTF_COMMON_SRC_METADATA_CTF_IR_HPP
+
+#include <cstdlib>
+#include <set>
+#include <vector>
+
+#include "cpp-common/bt2/trace-ir.hpp"
+#include "cpp-common/bt2c/observable.hpp"
+#include "cpp-common/bt2c/text-loc.hpp"
+#include "cpp-common/vendor/wise-enum/wise_enum.h"
+
+#include "../../metadata/ctf-ir.hpp"
+
+namespace ctf {
+namespace src {
+
+/*
+ * This is the CTF IR API specific to source component classes.
+ *
+ * This API defines a few internal user mixins for our needs to reuse
+ * the common `ctf::ir` API.
+ *
+ * In general, if a C++ class C has a libCls() method, then if libCls()
+ * returns a value for a given instance X, then consider that all the
+ * dependent field classes of X have a saved key value index (more about
+ * this below).
+ */
+
+/* clang-format off */
+
+/*
+ * The deep type of a field class is a superset of `ctf::ir::FcType`
+ * which contains additional, static information about the field class.
+ *
+ * For fixed-length and variable-length field classes, this deep type
+ * incorporates important decoding information, for example:
+ *
+ * • Byte order.
+ *
+ * • Whether or not the bit order is reversed (unnatural).
+ *
+ * • Whether or not it's a "standard" fixed-length bit array.
+ *
+ * • Length, if it's a "standard" fixed-length bit array.
+ *
+ * • Integer signedness.
+ *
+ * • Whether or not the field has a role.
+ *
+ * • Whether or not the value of the field has to be saved as a
+ *   key value.
+ *
+ * The purpose of the deep type of a field class is to have a single
+ * `switch` statement in the field reading method of some data stream
+ * decoder to select its next state and make it easier/possible for the
+ * compiler to optimize as most common decisions are encoded in there.
+ *
+ * For example, if it's known that the next field to read is a
+ * little-endian, byte-aligned 32-bit unsigned integer field of which
+ * the data stream decoder needs to save the value, then its deep type
+ * is `FcDeepType::FixedLenUIntBa32LeSaveVal`, which means the decoder
+ * will jump to a specific, corresponding reading method directly. The
+ * latter method can do exactly what's needed to perform such a field
+ * reading operation efficiently (using bt2c::readFixedLenIntLe()) and
+ * save its value unconditionally.
+ *
+ * The enumerator names below use the following common parts:
+ *
+ * `Be`:
+ *     Big-endian.
+ *
+ * `Le`:
+ *     Little-endian.
+ *
+ * `Rev`:
+ *     Reversed (unnatural) bit order.
+ *
+ * `Ba`:
+ *     Byte-aligned (alignment of at least 8 bits).
+ *
+ * `8`, `16`, `32`, `64`:
+ *     Fixed 8-bit, 16-bit, 32-bit, or 64-bit length.
+ *
+ * `SaveVal`:
+ *     Save the value of the boolean/integer key field.
+ *
+ * `WithRole`:
+ *     Unsigned integer field with at least one role.
+ *
+ * `WithMetadataStreamUuidRole`:
+ *     Static-length array/BLOB field with the "metadata stream
+ *     UUID" role.
+ *
+ * `Utf*`:
+ *     String field with a specific UTF string encoding.
+ */
+WISE_ENUM_CLASS(FcDeepType,
+    /* Fixed-length bit array */
+    FixedLenBitArrayBa8,
+    FixedLenBitArrayBe,
+    FixedLenBitArrayBa16Be,
+    FixedLenBitArrayBa32Be,
+    FixedLenBitArrayBa64Be,
+    FixedLenBitArrayLe,
+    FixedLenBitArrayBa16Le,
+    FixedLenBitArrayBa32Le,
+    FixedLenBitArrayBa64Le,
+    FixedLenBitArrayBa8Rev,
+    FixedLenBitArrayBeRev,
+    FixedLenBitArrayBa16BeRev,
+    FixedLenBitArrayBa32BeRev,
+    FixedLenBitArrayBa64BeRev,
+    FixedLenBitArrayLeRev,
+    FixedLenBitArrayBa16LeRev,
+    FixedLenBitArrayBa32LeRev,
+    FixedLenBitArrayBa64LeRev,
+
+    /* Fixed-length bit map */
+    FixedLenBitMapBa8,
+    FixedLenBitMapBe,
+    FixedLenBitMapBa16Be,
+    FixedLenBitMapBa32Be,
+    FixedLenBitMapBa64Be,
+    FixedLenBitMapLe,
+    FixedLenBitMapBa16Le,
+    FixedLenBitMapBa32Le,
+    FixedLenBitMapBa64Le,
+    FixedLenBitMapBa8Rev,
+    FixedLenBitMapBeRev,
+    FixedLenBitMapBa16BeRev,
+    FixedLenBitMapBa32BeRev,
+    FixedLenBitMapBa64BeRev,
+    FixedLenBitMapLeRev,
+    FixedLenBitMapBa16LeRev,
+    FixedLenBitMapBa32LeRev,
+    FixedLenBitMapBa64LeRev,
+
+    /* Fixed-length boolean */
+    FixedLenBoolBa8,
+    FixedLenBoolBa8SaveVal,
+    FixedLenBoolBe,
+    FixedLenBoolBeSaveVal,
+    FixedLenBoolBa16Be,
+    FixedLenBoolBa16BeSaveVal,
+    FixedLenBoolBa32Be,
+    FixedLenBoolBa32BeSaveVal,
+    FixedLenBoolBa64Be,
+    FixedLenBoolBa64BeSaveVal,
+    FixedLenBoolLe,
+    FixedLenBoolLeSaveVal,
+    FixedLenBoolBa16Le,
+    FixedLenBoolBa16LeSaveVal,
+    FixedLenBoolBa32Le,
+    FixedLenBoolBa32LeSaveVal,
+    FixedLenBoolBa64Le,
+    FixedLenBoolBa64LeSaveVal,
+    FixedLenBoolBa8Rev,
+    FixedLenBoolBa8RevSaveVal,
+    FixedLenBoolBeRev,
+    FixedLenBoolBeRevSaveVal,
+    FixedLenBoolBa16BeRev,
+    FixedLenBoolBa16BeRevSaveVal,
+    FixedLenBoolBa32BeRev,
+    FixedLenBoolBa32BeRevSaveVal,
+    FixedLenBoolBa64BeRev,
+    FixedLenBoolBa64BeRevSaveVal,
+    FixedLenBoolLeRev,
+    FixedLenBoolLeRevSaveVal,
+    FixedLenBoolBa16LeRev,
+    FixedLenBoolBa16LeRevSaveVal,
+    FixedLenBoolBa32LeRev,
+    FixedLenBoolBa32LeRevSaveVal,
+    FixedLenBoolBa64LeRev,
+    FixedLenBoolBa64LeRevSaveVal,
+
+    /* Fixed-length floating-point number */
+    FixedLenFloat32Be,
+    FixedLenFloatBa32Be,
+    FixedLenFloat64Be,
+    FixedLenFloatBa64Be,
+    FixedLenFloat32Le,
+    FixedLenFloatBa32Le,
+    FixedLenFloat64Le,
+    FixedLenFloatBa64Le,
+    FixedLenFloat32BeRev,
+    FixedLenFloatBa32BeRev,
+    FixedLenFloat64BeRev,
+    FixedLenFloatBa64BeRev,
+    FixedLenFloat32LeRev,
+    FixedLenFloatBa32LeRev,
+    FixedLenFloat64LeRev,
+    FixedLenFloatBa64LeRev,
+
+    /* Fixed-length unsigned integer */
+    FixedLenUIntBa8,
+    FixedLenUIntBa8SaveVal,
+    FixedLenUIntBa8WithRole,
+    FixedLenUIntBa8WithRoleSaveVal,
+    FixedLenUIntBe,
+    FixedLenUIntBeSaveVal,
+    FixedLenUIntBeWithRole,
+    FixedLenUIntBeWithRoleSaveVal,
+    FixedLenUIntBa16Be,
+    FixedLenUIntBa16BeSaveVal,
+    FixedLenUIntBa16BeWithRole,
+    FixedLenUIntBa16BeWithRoleSaveVal,
+    FixedLenUIntBa32Be,
+    FixedLenUIntBa32BeSaveVal,
+    FixedLenUIntBa32BeWithRole,
+    FixedLenUIntBa32BeWithRoleSaveVal,
+    FixedLenUIntBa64Be,
+    FixedLenUIntBa64BeSaveVal,
+    FixedLenUIntBa64BeWithRole,
+    FixedLenUIntBa64BeWithRoleSaveVal,
+    FixedLenUIntLe,
+    FixedLenUIntLeSaveVal,
+    FixedLenUIntLeWithRole,
+    FixedLenUIntLeWithRoleSaveVal,
+    FixedLenUIntBa16Le,
+    FixedLenUIntBa16LeSaveVal,
+    FixedLenUIntBa16LeWithRole,
+    FixedLenUIntBa16LeWithRoleSaveVal,
+    FixedLenUIntBa32Le,
+    FixedLenUIntBa32LeSaveVal,
+    FixedLenUIntBa32LeWithRole,
+    FixedLenUIntBa32LeWithRoleSaveVal,
+    FixedLenUIntBa64Le,
+    FixedLenUIntBa64LeSaveVal,
+    FixedLenUIntBa64LeWithRole,
+    FixedLenUIntBa64LeWithRoleSaveVal,
+    FixedLenUIntBa8Rev,
+    FixedLenUIntBa8RevSaveVal,
+    FixedLenUIntBa8RevWithRole,
+    FixedLenUIntBa8RevWithRoleSaveVal,
+    FixedLenUIntBeRev,
+    FixedLenUIntBeRevSaveVal,
+    FixedLenUIntBeRevWithRole,
+    FixedLenUIntBeRevWithRoleSaveVal,
+    FixedLenUIntBa16BeRev,
+    FixedLenUIntBa16BeRevSaveVal,
+    FixedLenUIntBa16BeRevWithRole,
+    FixedLenUIntBa16BeRevWithRoleSaveVal,
+    FixedLenUIntBa32BeRev,
+    FixedLenUIntBa32BeRevSaveVal,
+    FixedLenUIntBa32BeRevWithRole,
+    FixedLenUIntBa32BeRevWithRoleSaveVal,
+    FixedLenUIntBa64BeRev,
+    FixedLenUIntBa64BeRevSaveVal,
+    FixedLenUIntBa64BeRevWithRole,
+    FixedLenUIntBa64BeRevWithRoleSaveVal,
+    FixedLenUIntLeRev,
+    FixedLenUIntLeRevSaveVal,
+    FixedLenUIntLeRevWithRole,
+    FixedLenUIntLeRevWithRoleSaveVal,
+    FixedLenUIntBa16LeRev,
+    FixedLenUIntBa16LeRevSaveVal,
+    FixedLenUIntBa16LeRevWithRole,
+    FixedLenUIntBa16LeRevWithRoleSaveVal,
+    FixedLenUIntBa32LeRev,
+    FixedLenUIntBa32LeRevSaveVal,
+    FixedLenUIntBa32LeRevWithRole,
+    FixedLenUIntBa32LeRevWithRoleSaveVal,
+    FixedLenUIntBa64LeRev,
+    FixedLenUIntBa64LeRevSaveVal,
+    FixedLenUIntBa64LeRevWithRole,
+    FixedLenUIntBa64LeRevWithRoleSaveVal,
+
+    /* Fixed-length signed integer */
+    FixedLenSIntBa8,
+    FixedLenSIntBa8SaveVal,
+    FixedLenSIntBe,
+    FixedLenSIntBeSaveVal,
+    FixedLenSIntBa16Be,
+    FixedLenSIntBa16BeSaveVal,
+    FixedLenSIntBa32Be,
+    FixedLenSIntBa32BeSaveVal,
+    FixedLenSIntBa64Be,
+    FixedLenSIntBa64BeSaveVal,
+    FixedLenSIntLe,
+    FixedLenSIntLeSaveVal,
+    FixedLenSIntBa16Le,
+    FixedLenSIntBa16LeSaveVal,
+    FixedLenSIntBa32Le,
+    FixedLenSIntBa32LeSaveVal,
+    FixedLenSIntBa64Le,
+    FixedLenSIntBa64LeSaveVal,
+    FixedLenSIntBa8Rev,
+    FixedLenSIntBa8RevSaveVal,
+    FixedLenSIntBeRev,
+    FixedLenSIntBeRevSaveVal,
+    FixedLenSIntBa16BeRev,
+    FixedLenSIntBa16BeRevSaveVal,
+    FixedLenSIntBa32BeRev,
+    FixedLenSIntBa32BeRevSaveVal,
+    FixedLenSIntBa64BeRev,
+    FixedLenSIntBa64BeRevSaveVal,
+    FixedLenSIntLeRev,
+    FixedLenSIntLeRevSaveVal,
+    FixedLenSIntBa16LeRev,
+    FixedLenSIntBa16LeRevSaveVal,
+    FixedLenSIntBa32LeRev,
+    FixedLenSIntBa32LeRevSaveVal,
+    FixedLenSIntBa64LeRev,
+    FixedLenSIntBa64LeRevSaveVal,
+
+    /* Variable-length unsigned integer */
+    VarLenUInt,
+    VarLenUIntSaveVal,
+    VarLenUIntWithRole,
+    VarLenUIntWithRoleSaveVal,
+
+    /* Variable-length signed integer */
+    VarLenSInt,
+    VarLenSIntSaveVal,
+
+    /* String */
+    NullTerminatedStrUtf8,
+    NullTerminatedStrUtf16,
+    NullTerminatedStrUtf32,
+    StaticLenStr,
+    DynLenStr,
+
+    /* BLOB */
+    StaticLenBlob,
+    StaticLenBlobWithMetadataStreamUuidRole,
+    DynLenBlob,
+
+    /* Array */
+    StaticLenArray,
+    StaticLenArrayWithMetadataStreamUuidRole,
+    DynLenArray,
+
+    /* Structure */
+    Struct,
+
+    /* Optional */
+    OptionalWithBoolSel,
+    OptionalWithUIntSel,
+    OptionalWithSIntSel,
+
+    /* Variant */
+    VariantWithUIntSel,
+    VariantWithSIntSel
+)
+
+/* clang-format on */
+
+/*
+ * Vector of key value saving indexes.
+ *
+ * The strategy to decode dynamic-length, optional, and variant fields
+ * (called _dependend_ fields) is for the data stream decoder to save
+ * the values of _key_ fields (boolean or integer fields) so that it can
+ * use them afterwards to decode dependent fields.
+ *
+ * A field class FC of which the deep type contains `SaveVal` contains
+ * key value saving indexes IX (keyValSavingIndexes() method).
+ * keyValSavingIndexes() possibly returns more than one index because
+ * many dependent fields may depend on the same key field.
+ *
+ * When decoding an instance of FC (a key field), the decoder saves its
+ * value to some vector V at the indexes IX. When decoding a dependent
+ * field, its class contains an index to retrieve a saved key value (its
+ * length or selector) from V.
+ */
+using KeyValSavingIndexes = std::vector<std::size_t>;
+
+namespace internal {
+
+struct CtfIrMixins;
+
+} /* namespace internal */
+
+/*
+ * Set of field class pointers.
+ */
+using FcSet = std::set<ir::Fc<internal::CtfIrMixins> *>;
+
+namespace internal {
+
+/*
+ * Field location user mixin.
+ */
+class FieldLocMixin
+{
+public:
+    explicit FieldLocMixin(const bt2c::TextLoc& loc) noexcept;
+
+    /*
+     * Text location of this field location within the metadata stream.
+     */
+    const bt2c::TextLoc& loc() const noexcept
+    {
+        return _mLoc;
+    }
+
+private:
+    /* Text location of this field location within the metadata stream */
+    bt2c::TextLoc _mLoc;
+};
+
+/*
+ * Clock class user mixin.
+ */
+class ClkClsMixin
+{
+public:
+    explicit ClkClsMixin() noexcept = default;
+
+    /*
+     * Sets the equivalent libbabeltrace2 class to `cls` (shared).
+     */
+    void sharedLibCls(bt2::ClockClass::Shared cls) noexcept;
+
+private:
+    /* Equivalent libbabeltrace2 class (shared) */
+    bt2::ClockClass::Shared _mSharedLibCls;
+};
+
+template <typename FcT>
+class KeyFcMixin;
+
+/*
+ * Field class user mixin.
+ */
+class FcMixin
+{
+    template <typename>
+    friend class KeyFcMixin;
+
+public:
+    explicit FcMixin(const bt2c::TextLoc& loc = bt2c::TextLoc {}) noexcept;
+
+    explicit FcMixin(FcDeepType deepType, const bt2c::TextLoc& loc = bt2c::TextLoc {}) noexcept;
+
+    /*
+     * Text location of this field class within the metadata stream.
+     */
+    const bt2c::TextLoc& loc() const noexcept
+    {
+        return _mLoc;
+    }
+
+    /*
+     * Deep type of this field class.
+     */
+    FcDeepType deepType() const noexcept
+    {
+        return _mDeepType;
+    }
+
+private:
+    /* Deep type of this field class */
+    FcDeepType _mDeepType;
+
+    /* Text location of this field class within the metadata stream */
+    bt2c::TextLoc _mLoc;
+};
+
+/*
+ * Internal mixin for a key field class `FcT`.
+ *
+ * See the comment of `ValSavingIndexes` to learn more.
+ */
+template <typename FcT>
+class KeyFcMixin
+{
+public:
+    explicit KeyFcMixin() noexcept {};
+
+    const KeyValSavingIndexes& keyValSavingIndexes() const noexcept
+    {
+        return _mKeyValSavingIndexes;
+    }
+
+    void addKeyValSavingIndex(const std::size_t index)
+    {
+        _mKeyValSavingIndexes.push_back(index);
+
+        auto& deepType = static_cast<FcT&>(*this)._mDeepType;
+
+        /*
+         * At this point we know that the data stream decoder needs to
+         * save the value of any instance of this field class (a
+         * key field).
+         *
+         * Adjust the deep type of the field class so as to include that
+         * it's a key one.
+         */
+        deepType = bt2c::call([deepType] {
+            switch (deepType) {
+            case FcDeepType::FixedLenBoolBa8:
+                return FcDeepType::FixedLenBoolBa8SaveVal;
+            case FcDeepType::FixedLenBoolBe:
+                return FcDeepType::FixedLenBoolBeSaveVal;
+            case FcDeepType::FixedLenBoolBa16Be:
+                return FcDeepType::FixedLenBoolBa16BeSaveVal;
+            case FcDeepType::FixedLenBoolBa32Be:
+                return FcDeepType::FixedLenBoolBa32BeSaveVal;
+            case FcDeepType::FixedLenBoolBa64Be:
+                return FcDeepType::FixedLenBoolBa64BeSaveVal;
+            case FcDeepType::FixedLenBoolLe:
+                return FcDeepType::FixedLenBoolLeSaveVal;
+            case FcDeepType::FixedLenBoolBa16Le:
+                return FcDeepType::FixedLenBoolBa16LeSaveVal;
+            case FcDeepType::FixedLenBoolBa32Le:
+                return FcDeepType::FixedLenBoolBa32LeSaveVal;
+            case FcDeepType::FixedLenBoolBa64Le:
+                return FcDeepType::FixedLenBoolBa64LeSaveVal;
+            case FcDeepType::FixedLenBoolBa8Rev:
+                return FcDeepType::FixedLenBoolBa8RevSaveVal;
+            case FcDeepType::FixedLenBoolBeRev:
+                return FcDeepType::FixedLenBoolBeRevSaveVal;
+            case FcDeepType::FixedLenBoolBa16BeRev:
+                return FcDeepType::FixedLenBoolBa16BeRevSaveVal;
+            case FcDeepType::FixedLenBoolBa32BeRev:
+                return FcDeepType::FixedLenBoolBa32BeRevSaveVal;
+            case FcDeepType::FixedLenBoolBa64BeRev:
+                return FcDeepType::FixedLenBoolBa64BeRevSaveVal;
+            case FcDeepType::FixedLenBoolLeRev:
+                return FcDeepType::FixedLenBoolLeRevSaveVal;
+            case FcDeepType::FixedLenBoolBa16LeRev:
+                return FcDeepType::FixedLenBoolBa16LeRevSaveVal;
+            case FcDeepType::FixedLenBoolBa32LeRev:
+                return FcDeepType::FixedLenBoolBa32LeRevSaveVal;
+            case FcDeepType::FixedLenBoolBa64LeRev:
+                return FcDeepType::FixedLenBoolBa64LeRevSaveVal;
+            case FcDeepType::FixedLenUIntBa8:
+                return FcDeepType::FixedLenUIntBa8SaveVal;
+            case FcDeepType::FixedLenUIntBa8WithRole:
+                return FcDeepType::FixedLenUIntBa8WithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBe:
+                return FcDeepType::FixedLenUIntBeSaveVal;
+            case FcDeepType::FixedLenUIntBeWithRole:
+                return FcDeepType::FixedLenUIntBeWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa16Be:
+                return FcDeepType::FixedLenUIntBa16BeSaveVal;
+            case FcDeepType::FixedLenUIntBa16BeWithRole:
+                return FcDeepType::FixedLenUIntBa16BeWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa32Be:
+                return FcDeepType::FixedLenUIntBa32BeSaveVal;
+            case FcDeepType::FixedLenUIntBa32BeWithRole:
+                return FcDeepType::FixedLenUIntBa32BeWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa64Be:
+                return FcDeepType::FixedLenUIntBa64BeSaveVal;
+            case FcDeepType::FixedLenUIntBa64BeWithRole:
+                return FcDeepType::FixedLenUIntBa64BeWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntLe:
+                return FcDeepType::FixedLenUIntLeSaveVal;
+            case FcDeepType::FixedLenUIntLeWithRole:
+                return FcDeepType::FixedLenUIntLeWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa16Le:
+                return FcDeepType::FixedLenUIntBa16LeSaveVal;
+            case FcDeepType::FixedLenUIntBa16LeWithRole:
+                return FcDeepType::FixedLenUIntBa16LeWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa32Le:
+                return FcDeepType::FixedLenUIntBa32LeSaveVal;
+            case FcDeepType::FixedLenUIntBa32LeWithRole:
+                return FcDeepType::FixedLenUIntBa32LeWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa64Le:
+                return FcDeepType::FixedLenUIntBa64LeSaveVal;
+            case FcDeepType::FixedLenUIntBa64LeWithRole:
+                return FcDeepType::FixedLenUIntBa64LeWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa8Rev:
+                return FcDeepType::FixedLenUIntBa8RevSaveVal;
+            case FcDeepType::FixedLenUIntBa8RevWithRole:
+                return FcDeepType::FixedLenUIntBa8RevWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBeRev:
+                return FcDeepType::FixedLenUIntBeRevSaveVal;
+            case FcDeepType::FixedLenUIntBeRevWithRole:
+                return FcDeepType::FixedLenUIntBeRevWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa16BeRev:
+                return FcDeepType::FixedLenUIntBa16BeRevSaveVal;
+            case FcDeepType::FixedLenUIntBa16BeRevWithRole:
+                return FcDeepType::FixedLenUIntBa16BeRevWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa32BeRev:
+                return FcDeepType::FixedLenUIntBa32BeRevSaveVal;
+            case FcDeepType::FixedLenUIntBa32BeRevWithRole:
+                return FcDeepType::FixedLenUIntBa32BeRevWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa64BeRev:
+                return FcDeepType::FixedLenUIntBa64BeRevSaveVal;
+            case FcDeepType::FixedLenUIntBa64BeRevWithRole:
+                return FcDeepType::FixedLenUIntBa64BeRevWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntLeRev:
+                return FcDeepType::FixedLenUIntLeRevSaveVal;
+            case FcDeepType::FixedLenUIntLeRevWithRole:
+                return FcDeepType::FixedLenUIntLeRevWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa16LeRev:
+                return FcDeepType::FixedLenUIntBa16LeRevSaveVal;
+            case FcDeepType::FixedLenUIntBa16LeRevWithRole:
+                return FcDeepType::FixedLenUIntBa16LeRevWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa32LeRev:
+                return FcDeepType::FixedLenUIntBa32LeRevSaveVal;
+            case FcDeepType::FixedLenUIntBa32LeRevWithRole:
+                return FcDeepType::FixedLenUIntBa32LeRevWithRoleSaveVal;
+            case FcDeepType::FixedLenUIntBa64LeRev:
+                return FcDeepType::FixedLenUIntBa64LeRevSaveVal;
+            case FcDeepType::FixedLenUIntBa64LeRevWithRole:
+                return FcDeepType::FixedLenUIntBa64LeRevWithRoleSaveVal;
+            case FcDeepType::FixedLenSIntBa8:
+                return FcDeepType::FixedLenSIntBa8SaveVal;
+            case FcDeepType::FixedLenSIntBe:
+                return FcDeepType::FixedLenSIntBeSaveVal;
+            case FcDeepType::FixedLenSIntBa16Be:
+                return FcDeepType::FixedLenSIntBa16BeSaveVal;
+            case FcDeepType::FixedLenSIntBa32Be:
+                return FcDeepType::FixedLenSIntBa32BeSaveVal;
+            case FcDeepType::FixedLenSIntBa64Be:
+                return FcDeepType::FixedLenSIntBa64BeSaveVal;
+            case FcDeepType::FixedLenSIntLe:
+                return FcDeepType::FixedLenSIntLeSaveVal;
+            case FcDeepType::FixedLenSIntBa16Le:
+                return FcDeepType::FixedLenSIntBa16LeSaveVal;
+            case FcDeepType::FixedLenSIntBa32Le:
+                return FcDeepType::FixedLenSIntBa32LeSaveVal;
+            case FcDeepType::FixedLenSIntBa64Le:
+                return FcDeepType::FixedLenSIntBa64LeSaveVal;
+            case FcDeepType::FixedLenSIntBa8Rev:
+                return FcDeepType::FixedLenSIntBa8RevSaveVal;
+            case FcDeepType::FixedLenSIntBeRev:
+                return FcDeepType::FixedLenSIntBeRevSaveVal;
+            case FcDeepType::FixedLenSIntBa16BeRev:
+                return FcDeepType::FixedLenSIntBa16BeRevSaveVal;
+            case FcDeepType::FixedLenSIntBa32BeRev:
+                return FcDeepType::FixedLenSIntBa32BeRevSaveVal;
+            case FcDeepType::FixedLenSIntBa64BeRev:
+                return FcDeepType::FixedLenSIntBa64BeRevSaveVal;
+            case FcDeepType::FixedLenSIntLeRev:
+                return FcDeepType::FixedLenSIntLeRevSaveVal;
+            case FcDeepType::FixedLenSIntBa16LeRev:
+                return FcDeepType::FixedLenSIntBa16LeRevSaveVal;
+            case FcDeepType::FixedLenSIntBa32LeRev:
+                return FcDeepType::FixedLenSIntBa32LeRevSaveVal;
+            case FcDeepType::FixedLenSIntBa64LeRev:
+                return FcDeepType::FixedLenSIntBa64LeRevSaveVal;
+            case FcDeepType::VarLenUInt:
+                return FcDeepType::VarLenUIntSaveVal;
+            case FcDeepType::VarLenUIntWithRole:
+                return FcDeepType::VarLenUIntWithRoleSaveVal;
+            case FcDeepType::VarLenSInt:
+                return FcDeepType::VarLenSIntSaveVal;
+            default:
+                return deepType;
+            }
+        });
+    }
+
+private:
+    /* Value saving indexes */
+    KeyValSavingIndexes _mKeyValSavingIndexes;
+};
+
+/*
+ * Internal mixin for a dependent (dynamic-length, optional, or variant)
+ * field class.
+ *
+ * See the comment of `ValSavingIndexes` to learn more.
+ */
+class DependentFcMixin
+{
+public:
+    explicit DependentFcMixin() noexcept {};
+
+    /*
+     * Index of the saved key value of this field class.
+     */
+    const bt2s::optional<std::size_t>& savedKeyValIndex() const noexcept
+    {
+        return _mSavedKeyValIndex;
+    }
+
+    /*
+     * Sets the index of the saved key value of this field class
+     * to `savedKeyValIndex`.
+     *
+     * ┌────────────────────────────────────────────────────────────┐
+     * │ IMPORTANT: Only call this method if you can guarantee that │
+     * │ you won't clone `*this` (through Fc::clone()).             │
+     * └────────────────────────────────────────────────────────────┘
+     */
+    void savedKeyValIndex(const std::size_t savedKeyValIndex) noexcept
+    {
+        _mSavedKeyValIndex = savedKeyValIndex;
+    }
+
+    /*
+     * Key field classes of this field class.
+     */
+    const FcSet& keyFcs() noexcept
+    {
+        return _mKeyFcs;
+    }
+
+    /*
+     * Sets the key field classes of this field class to `keyFcs`.
+     *
+     * ┌────────────────────────────────────────────────────────────┐
+     * │ IMPORTANT: Only call this method if you can guarantee that │
+     * │ you won't clone `*this` (through Fc::clone()).             │
+     * └────────────────────────────────────────────────────────────┘
+     */
+    void keyFcs(FcSet keyFcs);
+
+private:
+    /* Index of the saved key value of this field class */
+    bt2s::optional<std::size_t> _mSavedKeyValIndex;
+
+    /* Dependencies of this field class */
+    FcSet _mKeyFcs;
+};
+
+/*
+ * Trace class user mixin.
+ */
+class TraceClsMixin
+{
+public:
+    using SavedKeyValCountUpdatedObservable = bt2c::Observable<std::size_t>;
+
+public:
+    explicit TraceClsMixin() noexcept {};
+
+    /*
+     * Sets the equivalent libbabeltrace2 class to `cls` (shared).
+     */
+    void sharedLibCls(bt2::TraceClass::Shared cls) noexcept;
+
+    /*
+     * Maximum number of saved key values for an instance of this
+     * trace class.
+     *
+     * See the comment of `ValSavingIndexes` to learn more.
+     */
+    std::size_t savedKeyValCount() const noexcept
+    {
+        return _mSavedKeyValCount;
+    }
+
+    /*
+     * Sets the maximum number of saved key values for an instance of
+     * this trace class to `savedKeyValCount`.
+     *
+     * See the comment of `ValSavingIndexes` to learn more.
+     */
+    void savedKeyValCount(const std::size_t savedKeyValCount) noexcept
+    {
+        _mSavedKeyValCount = savedKeyValCount;
+        _mSavedKeyValCountUpdatedObservable.notify(_mSavedKeyValCount);
+    }
+
+    /*
+     * Observable notified when the number of saved keys values required
+     * by this trace class changes.
+     */
+    SavedKeyValCountUpdatedObservable& savedKeyValCountUpdatedObservable() const
+    {
+        return _mSavedKeyValCountUpdatedObservable;
+    }
+
+private:
+    /* Equivalent libbabeltrace2 class (shared) */
+    bt2::TraceClass::Shared _mSharedLibCls;
+
+    /*
+     * Maximum number of saved key values for an instance of this
+     * trace class.
+     *
+     * See the comment of `ValSavingIndexes` to learn more.
+     */
+    std::size_t _mSavedKeyValCount = 0;
+
+    /*
+     * Observable notified when the number of saved key values required
+     * by this trace class changes.
+     */
+    mutable SavedKeyValCountUpdatedObservable _mSavedKeyValCountUpdatedObservable;
+};
+
+/*
+ * User mixin container.
+ */
+struct CtfIrMixins final : public ir::DefUserMixins
+{
+    using FieldLoc = FieldLocMixin;
+    using ClkCls = ClkClsMixin;
+    using Fc = FcMixin;
+    using FixedLenBoolFc = KeyFcMixin<ir::FixedLenBoolFc<internal::CtfIrMixins>>;
+    using FixedLenIntFc = KeyFcMixin<ir::FixedLenIntFc<internal::CtfIrMixins>>;
+    using VarLenIntFc = KeyFcMixin<ir::VarLenIntFc<internal::CtfIrMixins>>;
+    using DynLenStrFc = DependentFcMixin;
+    using DynLenBlobFc = DependentFcMixin;
+    using DynLenArrayFc = DependentFcMixin;
+    using VariantFc = DependentFcMixin;
+    using OptionalFc = DependentFcMixin;
+    using TraceCls = TraceClsMixin;
+};
+
+} /* namespace internal */
+
+/* Aliases of the `ctf::src` CTF IR API */
+using ArrayFc = ir::ArrayFc<internal::CtfIrMixins>;
+using BitOrder = ir::BitOrder;
+using BlobFc = ir::BlobFc<internal::CtfIrMixins>;
+using ByteOrder = ir::ByteOrder;
+using ClkCls = ir::ClkCls<internal::CtfIrMixins>;
+using ClkOffset = ir::ClkOffset;
+using ClkOrigin = ir::ClkOrigin;
+using ConstFcVisitor = ir::ConstFcVisitor<internal::CtfIrMixins>;
+using DataStreamCls = ir::DataStreamCls<internal::CtfIrMixins>;
+using DispBase = ir::DispBase;
+using DynLenArrayFc = ir::DynLenArrayFc<internal::CtfIrMixins>;
+using DynLenBlobFc = ir::DynLenBlobFc<internal::CtfIrMixins>;
+using DynLenStrFc = ir::DynLenStrFc<internal::CtfIrMixins>;
+using EventRecordCls = ir::EventRecordCls<internal::CtfIrMixins>;
+using Fc = ir::Fc<internal::CtfIrMixins>;
+using FcType = ir::FcType;
+using FcVisitor = ir::FcVisitor<internal::CtfIrMixins>;
+using FieldLoc = ir::FieldLoc<internal::CtfIrMixins>;
+using FixedLenBitArrayFc = ir::FixedLenBitArrayFc<internal::CtfIrMixins>;
+using FixedLenBitMapFc = ir::FixedLenBitMapFc<internal::CtfIrMixins>;
+using FixedLenBoolFc = ir::FixedLenBoolFc<internal::CtfIrMixins>;
+using FixedLenFloatFc = ir::FixedLenFloatFc<internal::CtfIrMixins>;
+using FixedLenIntFc = ir::FixedLenIntFc<internal::CtfIrMixins>;
+using FixedLenSIntFc = ir::FixedLenSIntFc<internal::CtfIrMixins>;
+using FixedLenUIntFc = ir::FixedLenUIntFc<internal::CtfIrMixins>;
+using NonNullTerminatedStrFc = ir::NonNullTerminatedStrFc<internal::CtfIrMixins>;
+using NullTerminatedStrFc = ir::NullTerminatedStrFc<internal::CtfIrMixins>;
+using OptionalFc = ir::OptionalFc<internal::CtfIrMixins>;
+using OptionalWithBoolSelFc = ir::OptionalWithBoolSelFc<internal::CtfIrMixins>;
+using OptionalWithSIntSelFc = ir::OptionalWithSIntSelFc<internal::CtfIrMixins>;
+using OptionalWithUIntSelFc = ir::OptionalWithUIntSelFc<internal::CtfIrMixins>;
+using OptAttrs = ir::OptAttrs;
+using Scope = ir::Scope;
+using StaticLenArrayFc = ir::StaticLenArrayFc<internal::CtfIrMixins>;
+using StaticLenBlobFc = ir::StaticLenBlobFc<internal::CtfIrMixins>;
+using StaticLenStrFc = ir::StaticLenStrFc<internal::CtfIrMixins>;
+using StrEncoding = ir::StrEncoding;
+using StrFc = ir::StrFc<internal::CtfIrMixins>;
+using StructFc = ir::StructFc<internal::CtfIrMixins>;
+using StructFieldMemberCls = ir::StructFieldMemberCls<internal::CtfIrMixins>;
+using TraceCls = ir::TraceCls<internal::CtfIrMixins>;
+using UIntFieldRole = ir::UIntFieldRole;
+using UIntFieldRoles = ir::UIntFieldRoles;
+using VariantWithSIntSelFc = ir::VariantWithSIntSelFc<internal::CtfIrMixins>;
+using VariantWithUIntSelFc = ir::VariantWithUIntSelFc<internal::CtfIrMixins>;
+using VarLenIntFc = ir::VarLenIntFc<internal::CtfIrMixins>;
+using VarLenSIntFc = ir::VarLenSIntFc<internal::CtfIrMixins>;
+using VarLenUIntFc = ir::VarLenUIntFc<internal::CtfIrMixins>;
+
+/*
+ * Creates and returns a field location having the origin `origin` and
+ * the path items `items`.
+ */
+FieldLoc createFieldLoc(const bt2c::TextLoc& loc, bt2s::optional<Scope> origin,
+                        FieldLoc::Items items);
+
+/*
+ * Overload without a text location.
+ */
+inline FieldLoc createFieldLoc(bt2s::optional<Scope> origin, FieldLoc::Items items)
+{
+    return createFieldLoc(bt2c::TextLoc {}, std::move(origin), std::move(items));
+}
+
+/*
+ * Creates and returns a class of fixed-length bit array fields having
+ * the alignment `align` bits, the length `len`, the byte order
+ * `byteOrder`, the bit order `bitOrder`, and the attributes `attrs`.
+ */
+std::unique_ptr<FixedLenBitArrayFc> createFixedLenBitArrayFc(
+    const bt2c::TextLoc& loc, unsigned int align, bt2c::DataLen len, ByteOrder byteOrder,
+    const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt, OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of fixed-length bit map fields having the
+ * alignment `align` bits, the length `len`, the byte order `byteOrder`,
+ * the bit order `bitOrder`, the flags `flags`, and the
+ * attributes `attrs`.
+ */
+std::unique_ptr<FixedLenBitMapFc>
+createFixedLenBitMapFc(const bt2c::TextLoc& loc, unsigned int align, bt2c::DataLen len,
+                       ByteOrder byteOrder, FixedLenBitMapFc::Flags flags,
+                       const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+                       OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of fixed-length boolean fields having the
+ * alignment `align` bits, the length `len`, the byte order `byteOrder`,
+ * the bit order `bitOrder`, and the attributes `attrs`.
+ */
+std::unique_ptr<FixedLenBoolFc>
+createFixedLenBoolFc(const bt2c::TextLoc& loc, unsigned int align, bt2c::DataLen len,
+                     ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+                     OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of fixed-length floating point number
+ * fields having the alignment `align` bits, the length `len`, the byte
+ * order `byteOrder`, the bit order `bitOrder`, and the
+ * attributes `attrs`.
+ */
+std::unique_ptr<FixedLenFloatFc>
+createFixedLenFloatFc(const bt2c::TextLoc& loc, unsigned int align, bt2c::DataLen len,
+                      ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+                      OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<FixedLenFloatFc>
+createFixedLenFloatFc(const unsigned int align, const bt2c::DataLen len, const ByteOrder byteOrder,
+                      const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+                      OptAttrs attrs = OptAttrs {})
+{
+    return createFixedLenFloatFc(bt2c::TextLoc {}, align, len, byteOrder, bitOrder,
+                                 std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of fixed-length unsigned integer fields
+ * having the alignment `align` bits, the length `len`, the byte order
+ * `byteOrder`, the bit order `bitOrder`, the preferred display base
+ * `prefDispBase`, the mappings `mappings`, the roles `roles`, and the
+ * attributes `attrs`.
+ */
+std::unique_ptr<FixedLenUIntFc>
+createFixedLenUIntFc(const bt2c::TextLoc& loc, unsigned int align, bt2c::DataLen len,
+                     ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+                     DispBase prefDispBase = DispBase::Dec, FixedLenUIntFc::Mappings mappings = {},
+                     UIntFieldRoles roles = {}, OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<FixedLenUIntFc>
+createFixedLenUIntFc(const unsigned int align, const bt2c::DataLen len, const ByteOrder byteOrder,
+                     const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+                     const DispBase prefDispBase = DispBase::Dec,
+                     FixedLenUIntFc::Mappings mappings = {}, UIntFieldRoles roles = {},
+                     OptAttrs attrs = OptAttrs {})
+{
+    return createFixedLenUIntFc(bt2c::TextLoc {}, align, len, byteOrder, bitOrder, prefDispBase,
+                                std::move(mappings), std::move(roles), std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of fixed-length signed integer fields
+ * having the alignment `align` bits, the length `len`, the byte order
+ * `byteOrder`, the bit order `bitOrder`, the preferred display base
+ * `prefDispBase`, the mappings `mappings`, and the attributes `attrs`.
+ */
+std::unique_ptr<FixedLenSIntFc>
+createFixedLenSIntFc(const bt2c::TextLoc& loc, unsigned int align, bt2c::DataLen len,
+                     ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+                     DispBase prefDispBase = DispBase::Dec, FixedLenSIntFc::Mappings mappings = {},
+                     OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<FixedLenSIntFc>
+createFixedLenSIntFc(const unsigned int align, const bt2c::DataLen len, const ByteOrder byteOrder,
+                     const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+                     const DispBase prefDispBase = DispBase::Dec,
+                     FixedLenSIntFc::Mappings mappings = {}, OptAttrs attrs = OptAttrs {})
+{
+    return createFixedLenSIntFc(bt2c::TextLoc {}, align, len, byteOrder, bitOrder, prefDispBase,
+                                std::move(mappings), std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of variable-length unsigned integer
+ * fields having the preferred display base `prefDispBase`, the mappings
+ * `mappings`, the roles `roles`, and the attributes `attrs`.
+ */
+std::unique_ptr<VarLenUIntFc> createVarLenUIntFc(const bt2c::TextLoc& loc,
+                                                 DispBase prefDispBase = DispBase::Dec,
+                                                 VarLenUIntFc::Mappings mappings = {},
+                                                 UIntFieldRoles roles = {},
+                                                 OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<VarLenUIntFc> createVarLenUIntFc(const DispBase prefDispBase = DispBase::Dec,
+                                                        VarLenUIntFc::Mappings mappings = {},
+                                                        UIntFieldRoles roles = {},
+                                                        OptAttrs attrs = OptAttrs {})
+{
+    return createVarLenUIntFc(bt2c::TextLoc {}, prefDispBase, std::move(mappings), std::move(roles),
+                              std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of variable-length signed integer fields
+ * having, the preferred display base `prefDispBase`, the mappings
+ * `mappings`, and the attributes `attrs`.
+ */
+std::unique_ptr<VarLenSIntFc> createVarLenSIntFc(const bt2c::TextLoc& loc,
+                                                 DispBase prefDispBase = DispBase::Dec,
+                                                 VarLenSIntFc::Mappings mappings = {},
+                                                 OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<VarLenSIntFc> createVarLenSIntFc(const DispBase prefDispBase = DispBase::Dec,
+                                                        VarLenSIntFc::Mappings mappings = {},
+                                                        OptAttrs attrs = OptAttrs {})
+{
+    return createVarLenSIntFc(bt2c::TextLoc {}, prefDispBase, std::move(mappings),
+                              std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of null-terminated fields having the
+ * encoding `encoding` and the attributes `attrs`.
+ */
+std::unique_ptr<NullTerminatedStrFc>
+createNullTerminatedStrFc(const bt2c::TextLoc& loc, StrEncoding encoding = StrEncoding::Utf8,
+                          OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+std::unique_ptr<NullTerminatedStrFc> inline createNullTerminatedStrFc(
+    const StrEncoding encoding = StrEncoding::Utf8, OptAttrs attrs = OptAttrs {})
+{
+    return createNullTerminatedStrFc(bt2c::TextLoc {}, encoding, std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of static-length string fields having the
+ * length `len` bytes, the encoding `encoding`, and the
+ * attributes `attrs`.
+ */
+std::unique_ptr<StaticLenStrFc> createStaticLenStrFc(const bt2c::TextLoc& loc, std::size_t len,
+                                                     StrEncoding encoding = StrEncoding::Utf8,
+                                                     OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<StaticLenStrFc>
+createStaticLenStrFc(const std::size_t len, const StrEncoding encoding = StrEncoding::Utf8,
+                     OptAttrs attrs = OptAttrs {})
+{
+    return createStaticLenStrFc(bt2c::TextLoc {}, len, encoding, std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of dynamic-length string fields having
+ * the length field location `lenFieldLoc`, the encoding `encoding`, and
+ * the attributes `attrs`.
+ */
+std::unique_ptr<DynLenStrFc> createDynLenStrFc(const bt2c::TextLoc& loc, FieldLoc lenFieldLoc,
+                                               StrEncoding encoding = StrEncoding::Utf8,
+                                               OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<DynLenStrFc>
+createDynLenStrFc(FieldLoc lenFieldLoc, const StrEncoding encoding = StrEncoding::Utf8,
+                  OptAttrs attrs = OptAttrs {})
+{
+    return createDynLenStrFc(bt2c::TextLoc {}, std::move(lenFieldLoc), encoding, std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of static-length BLOB fields having the
+ * length `len` bytes, the media type `mediaType`, the "metadata stream
+ * Uuid" role if `hasMetadataStreamUuidRole` is true, and the user
+ * attributes `attrs`.
+ */
+std::unique_ptr<StaticLenBlobFc>
+createStaticLenBlobFc(const bt2c::TextLoc& loc, std::size_t len,
+                      std::string mediaType = ir::defaultBlobMediaType,
+                      bool hasMetadataStreamUuidRole = false, OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of dynamic-length BLOB fields having the
+ * length field location `lenFieldLoc`, the media type `mediaType`, and
+ * the attributes `attrs`.
+ */
+std::unique_ptr<DynLenBlobFc> createDynLenBlobFc(const bt2c::TextLoc& loc, FieldLoc lenFieldLoc,
+                                                 std::string mediaType = ir::defaultBlobMediaType,
+                                                 OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of static-length array fields having the
+ * length `len`, the element field class `elemFc`, the minimum alignment
+ * `minAlign` bits, the attributes `attrs`, and the "metadata stream
+ * Uuid" role if `hasMetadataStreamUuidRole` is true.
+ */
+std::unique_ptr<StaticLenArrayFc> createStaticLenArrayFc(const bt2c::TextLoc& loc, std::size_t len,
+                                                         Fc::UP elemFc, unsigned int minAlign = 1,
+                                                         bool hasMetadataStreamUuidRole = false,
+                                                         OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<StaticLenArrayFc>
+createStaticLenArrayFc(const std::size_t len, Fc::UP elemFc, const unsigned int minAlign = 1,
+                       const bool hasMetadataStreamUuidRole = false, OptAttrs attrs = OptAttrs {})
+{
+    return createStaticLenArrayFc(bt2c::TextLoc {}, len, std::move(elemFc), minAlign,
+                                  hasMetadataStreamUuidRole, std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of dynamic-length array fields having the
+ * length field location `lenFieldLoc`, the element field class
+ * `elemFc`, the minimum alignment `minAlign` bits, and the user
+ * attributes `attrs`.
+ */
+std::unique_ptr<DynLenArrayFc> createDynLenArrayFc(const bt2c::TextLoc& loc, FieldLoc lenFieldLoc,
+                                                   Fc::UP elemFc, unsigned int minAlign = 1,
+                                                   OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<DynLenArrayFc> createDynLenArrayFc(FieldLoc lenFieldLoc, Fc::UP elemFc,
+                                                          const unsigned int minAlign = 1,
+                                                          OptAttrs attrs = OptAttrs {})
+{
+    return createDynLenArrayFc(bt2c::TextLoc {}, std::move(lenFieldLoc), std::move(elemFc),
+                               minAlign, std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of structure field members having the
+ * name `name`, the field class `fc`, and the attributes `attrs`.
+ */
+StructFieldMemberCls createStructFieldMemberCls(std::string name, Fc::UP fc,
+                                                OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of structure fields having members of
+ * classes `memberClasses`, the minimum alignment `minAlign` bits, and
+ * the attributes `attrs`.
+ */
+std::unique_ptr<StructFc> createStructFc(const bt2c::TextLoc& loc,
+                                         StructFc::MemberClasses&& memberClasses = {},
+                                         unsigned int minAlign = 1, OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<StructFc> createStructFc(StructFc::MemberClasses&& memberClasses = {},
+                                                const unsigned int minAlign = 1,
+                                                OptAttrs attrs = OptAttrs {})
+{
+    return createStructFc(bt2c::TextLoc {}, std::move(memberClasses), minAlign, std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of optional fields having a boolean
+ * selector, the optional field class `fc`, the selector field location
+ * `selFieldLoc`, and the attributes `attrs`.
+ */
+std::unique_ptr<OptionalWithBoolSelFc> createOptionalFc(const bt2c::TextLoc& loc, Fc::UP fc,
+                                                        FieldLoc selFieldLoc,
+                                                        OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of optional fields having an unsigned
+ * integer selector, the optional field class `fc`, the selector field
+ * location `selFieldLoc`, the integer selector field ranges
+ * `selFieldRanges`, and the attributes `attrs`.
+ */
+std::unique_ptr<OptionalWithUIntSelFc> createOptionalFc(const bt2c::TextLoc& loc, Fc::UP fc,
+                                                        FieldLoc selFieldLoc,
+                                                        UIntRangeSet selFieldRanges,
+                                                        OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of optional fields having a signed
+ * integer selector, the optional field class `fc`, the selector field
+ * location `selFieldLoc`, the integer selector field ranges
+ * `selFieldRanges`, and the attributes `attrs`.
+ */
+std::unique_ptr<OptionalWithSIntSelFc> createOptionalFc(const bt2c::TextLoc& loc, Fc::UP fc,
+                                                        FieldLoc selFieldLoc,
+                                                        SIntRangeSet selFieldRanges,
+                                                        OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns an option, for the class of a variant field
+ * having an unsigned integer selector, having the field class `fc`, the
+ * selector field ranges `selFieldRanges`, the name `name`, and the user
+ * attributes `attrs`.
+ */
+VariantWithUIntSelFc::Opt createVariantFcOpt(Fc::UP fc, UIntRangeSet selFieldRanges,
+                                             bt2s::optional<std::string> name,
+                                             OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns an option, for the class of a variant field
+ * having a signed integer selector, having the field class `fc`, the
+ * selector field ranges `selFieldRanges`, the name `name`, and the user
+ * attributes `attrs`.
+ */
+VariantWithSIntSelFc::Opt createVariantFcOpt(Fc::UP fc, SIntRangeSet selFieldRanges,
+                                             bt2s::optional<std::string> name,
+                                             OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of variant fields having an unsigned
+ * integer selector, the options `opts`, the selector field location
+ * `selFieldLoc`, and the attributes `attrs`.
+ */
+std::unique_ptr<VariantWithUIntSelFc> createVariantFc(const bt2c::TextLoc& loc,
+                                                      VariantWithUIntSelFc::Opts&& opts,
+                                                      FieldLoc selFieldLoc,
+                                                      OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<VariantWithUIntSelFc> createVariantFc(VariantWithUIntSelFc::Opts&& opts,
+                                                             FieldLoc selFieldLoc,
+                                                             OptAttrs attrs = OptAttrs {})
+{
+    return createVariantFc(bt2c::TextLoc {}, std::move(opts), std::move(selFieldLoc),
+                           std::move(attrs));
+}
+
+/*
+ * Creates and returns a class of variant fields having a signed integer
+ * selector, the options `opts`, the selector field location
+ * `selFieldLoc`, and the attributes `attrs`.
+ */
+std::unique_ptr<VariantWithSIntSelFc> createVariantFc(const bt2c::TextLoc& loc,
+                                                      VariantWithSIntSelFc::Opts&& opts,
+                                                      FieldLoc selFieldLoc,
+                                                      OptAttrs attrs = OptAttrs {});
+
+/*
+ * Overload without a text location.
+ */
+inline std::unique_ptr<VariantWithSIntSelFc> createVariantFc(VariantWithSIntSelFc::Opts&& opts,
+                                                             FieldLoc selFieldLoc,
+                                                             OptAttrs attrs = OptAttrs {})
+{
+    return createVariantFc(bt2c::TextLoc {}, std::move(opts), std::move(selFieldLoc),
+                           std::move(attrs));
+}
+
+/*
+ * Creates and returns a class, having the ID `id` (unique within its
+ * trace class), of a clocks having the frequency `freq` Hz, the
+ * namespace `ns`, the name `name`, the UID `uid`, the offset from
+ * origin `offset`, the origin `origin`, the description `descr`, the
+ * precision `precision` cycles, the accuracy `accuracy` cycles, and the
+ * attributes `attrs`.
+ */
+ClkCls::SP createClkCls(std::string id, unsigned long long freq,
+                        bt2s::optional<std::string> ns = bt2s::nullopt,
+                        bt2s::optional<std::string> name = bt2s::nullopt,
+                        bt2s::optional<std::string> uid = bt2s::nullopt,
+                        const ClkOffset& offset = ClkOffset {},
+                        bt2s::optional<ClkOrigin> origin = ClkOrigin {},
+                        bt2s::optional<std::string> descr = bt2s::nullopt,
+                        bt2s::optional<unsigned long long> precision = bt2s::nullopt,
+                        bt2s::optional<unsigned long long> accuracy = bt2s::nullopt,
+                        OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class, having the ID `id`, of event records
+ * having the namespace `ns`, the name `name`, the UID `uid`, the
+ * specific context field class `specCtxFc`, the payload field class
+ * `payloadFc`, and the attributes `attrs`.
+ */
+std::unique_ptr<EventRecordCls>
+createEventRecordCls(unsigned long long id, bt2s::optional<std::string> ns = bt2s::nullopt,
+                     bt2s::optional<std::string> name = bt2s::nullopt,
+                     bt2s::optional<std::string> uid = bt2s::nullopt, Fc::UP specCtxFc = nullptr,
+                     Fc::UP payloadFc = nullptr, OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class, having the ID `id`, of data streams
+ * having the the namespace `ns`, the name `name`, the UID `uid`, the
+ * packet context field class `pktCtxFc`, the event record header field
+ * class `eventRecordHeaderFc`, the common event record context field
+ * class `commonEventRecordCtxFc`, the default clock class `defClkCls`,
+ * and the attributes `attrs`.
+ */
+std::unique_ptr<DataStreamCls>
+createDataStreamCls(unsigned long long id, bt2s::optional<std::string> ns = bt2s::nullopt,
+                    bt2s::optional<std::string> name = bt2s::nullopt,
+                    bt2s::optional<std::string> uid = bt2s::nullopt, Fc::UP pktCtxFc = nullptr,
+                    Fc::UP eventRecordHeaderFc = nullptr, Fc::UP commonEventRecordCtxFc = nullptr,
+                    ClkCls::SP defClkCls = nullptr, OptAttrs attrs = OptAttrs {});
+
+/*
+ * Creates and returns a class of traces having the the namespace `ns`,
+ * the name `name`, the UID `uid`, the environment `env`, the packet
+ * header field class `pktHeaderFc`, and the attributes `attrs`.
+ */
+std::unique_ptr<TraceCls>
+createTraceCls(bt2s::optional<std::string> ns = bt2s::nullopt,
+               bt2s::optional<std::string> name = bt2s::nullopt,
+               bt2s::optional<std::string> uid = bt2s::nullopt,
+               bt2::ConstMapValue::Shared env = bt2::ConstMapValue::Shared {},
+               Fc::UP pktHeaderFc = nullptr, OptAttrs attrs = OptAttrs {});
+
+} /* namespace src */
+} /* namespace ctf */
+
+#endif /* BABELTRACE_PLUGINS_CTF_COMMON_SRC_METADATA_CTF_IR_HPP */
This page took 0.046402 seconds and 4 git commands to generate.