@@ -67,6 +67,53 @@ struct RNTupleClusterBoundaries {
6767std::vector<ROOT::Internal::RNTupleClusterBoundaries> GetClusterBoundaries (const RNTupleDescriptor &desc);
6868} // namespace Internal
6969
70+ namespace Experimental {
71+ namespace Internal {
72+ class RNTupleAttrSetDescriptorBuilder ;
73+ }
74+
75+ // clang-format off
76+ /* *
77+ \class ROOT::Experimental::RNTupleAttrSetDescriptor
78+ \ingroup NTuple
79+ \brief Metadata stored for every Attribute Set linked to an RNTuple.
80+ */
81+ // clang-format on
82+ class RNTupleAttrSetDescriptor final {
83+ friend class Experimental ::Internal::RNTupleAttrSetDescriptorBuilder;
84+
85+ std::uint16_t fSchemaVersionMajor = 0 ;
86+ std::uint16_t fSchemaVersionMinor = 0 ;
87+ std::uint32_t fAnchorLength = 0 ; // /< uncompressed size of the linked anchor
88+ // The locator of the AttributeSet anchor.
89+ // In case of kTypeFile, it points to the beginning of the Anchor's payload.
90+ // NOTE: Only kTypeFile is supported at the moment.
91+ RNTupleLocator fAnchorLocator ;
92+ std::string fName ;
93+
94+ public:
95+ RNTupleAttrSetDescriptor () = default ;
96+ RNTupleAttrSetDescriptor (const RNTupleAttrSetDescriptor &other) = delete ;
97+ RNTupleAttrSetDescriptor &operator =(const RNTupleAttrSetDescriptor &other) = delete ;
98+ RNTupleAttrSetDescriptor (RNTupleAttrSetDescriptor &&other) = default ;
99+ RNTupleAttrSetDescriptor &operator =(RNTupleAttrSetDescriptor &&other) = default ;
100+
101+ bool operator ==(const RNTupleAttrSetDescriptor &other) const ;
102+ bool operator !=(const RNTupleAttrSetDescriptor &other) const { return !(*this == other); }
103+
104+ const std::string &GetName () const { return fName ; }
105+ std::uint16_t GetSchemaVersionMajor () const { return fSchemaVersionMajor ; }
106+ std::uint16_t GetSchemaVersionMinor () const { return fSchemaVersionMinor ; }
107+ std::uint32_t GetAnchorLength () const { return fAnchorLength ; }
108+ const RNTupleLocator &GetAnchorLocator () const { return fAnchorLocator ; }
109+
110+ RNTupleAttrSetDescriptor Clone () const ;
111+ };
112+
113+ class RNTupleAttrSetDescriptorIterable ;
114+
115+ } // namespace Experimental
116+
70117// clang-format off
71118/* *
72119\class ROOT::RFieldDescriptor
@@ -697,6 +744,8 @@ private:
697744 std::vector<ROOT::DescriptorId_t> fSortedClusterGroupIds ;
698745 // / Potentially a subset of all the available clusters
699746 std::unordered_map<ROOT::DescriptorId_t, RClusterDescriptor> fClusterDescriptors ;
747+ // / List of AttributeSets linked to this RNTuple
748+ std::vector<Experimental::RNTupleAttrSetDescriptor> fAttributeSets ;
700749
701750 // We don't expose this publicly because when we add sharded clusters, this interface does not make sense anymore
702751 ROOT::DescriptorId_t FindClusterId (ROOT::NTupleSize_t entryIdx) const ;
@@ -714,6 +763,7 @@ public:
714763 class RClusterGroupDescriptorIterable ;
715764 class RClusterDescriptorIterable ;
716765 class RExtraTypeInfoDescriptorIterable ;
766+ friend class Experimental ::RNTupleAttrSetDescriptorIterable;
717767
718768 // / Modifiers passed to CreateModel()
719769 struct RCreateModelOptions {
@@ -802,6 +852,8 @@ public:
802852
803853 RExtraTypeInfoDescriptorIterable GetExtraTypeInfoIterable () const ;
804854
855+ ROOT::Experimental::RNTupleAttrSetDescriptorIterable GetAttrSetIterable () const ;
856+
805857 const std::string &GetName () const { return fName ; }
806858 const std::string &GetDescription () const { return fDescription ; }
807859
@@ -812,6 +864,7 @@ public:
812864 std::size_t GetNClusters () const { return fNClusters ; }
813865 std::size_t GetNActiveClusters () const { return fClusterDescriptors .size (); }
814866 std::size_t GetNExtraTypeInfos () const { return fExtraTypeInfoDescriptors .size (); }
867+ std::size_t GetNAttributeSets () const { return fAttributeSets .size (); }
815868
816869 // / We know the number of entries from adding the cluster summaries
817870 ROOT::NTupleSize_t GetNEntries () const { return fNEntries ; }
@@ -1141,6 +1194,59 @@ public:
11411194 RIterator end () { return RIterator (fNTuple .fExtraTypeInfoDescriptors .cend ()); }
11421195};
11431196
1197+ namespace Experimental {
1198+ // clang-format off
1199+ /* *
1200+ \class ROOT::Experimental::RNTupleAttrSetDescriptorIterable
1201+ \ingroup NTuple
1202+ \brief Used to loop over all the Attribute Sets linked to an RNTuple
1203+ */
1204+ // clang-format on
1205+ // TODO: move this to RNTupleDescriptor::RNTupleAttrSetDescriptorIterable when it moves out of Experimental.
1206+ class RNTupleAttrSetDescriptorIterable final {
1207+ private:
1208+ // / The associated RNTuple for this range.
1209+ const RNTupleDescriptor &fNTuple ;
1210+
1211+ public:
1212+ class RIterator final {
1213+ private:
1214+ using Iter_t = std::vector<RNTupleAttrSetDescriptor>::const_iterator;
1215+ // / The wrapped map iterator
1216+ Iter_t fIter ;
1217+
1218+ public:
1219+ using iterator_category = std::bidirectional_iterator_tag;
1220+ using iterator = RIterator;
1221+ using value_type = RNTupleAttrSetDescriptor;
1222+ using difference_type = std::ptrdiff_t ;
1223+ using pointer = const value_type *;
1224+ using reference = const value_type &;
1225+
1226+ RIterator (Iter_t iter) : fIter (iter) {}
1227+ iterator &operator ++() /* prefix */
1228+ {
1229+ ++fIter ;
1230+ return *this ;
1231+ }
1232+ iterator operator ++(int ) /* postfix */
1233+ {
1234+ auto old = *this ;
1235+ operator ++();
1236+ return old;
1237+ }
1238+ reference operator *() const { return *fIter ; }
1239+ pointer operator ->() const { return &*fIter ; }
1240+ bool operator !=(const iterator &rh) const { return fIter != rh.fIter ; }
1241+ bool operator ==(const iterator &rh) const { return fIter == rh.fIter ; }
1242+ };
1243+
1244+ RNTupleAttrSetDescriptorIterable (const RNTupleDescriptor &ntuple) : fNTuple (ntuple) {}
1245+ RIterator begin () { return RIterator (fNTuple .fAttributeSets .cbegin ()); }
1246+ RIterator end () { return RIterator (fNTuple .fAttributeSets .cend ()); }
1247+ };
1248+ } // namespace Experimental
1249+
11441250// clang-format off
11451251/* *
11461252\class ROOT::RNTupleDescriptor::RHeaderExtension
@@ -1214,6 +1320,39 @@ public:
12141320 }
12151321};
12161322
1323+ namespace Experimental ::Internal {
1324+ class RNTupleAttrSetDescriptorBuilder final {
1325+ ROOT::Experimental::RNTupleAttrSetDescriptor fDesc ;
1326+
1327+ public:
1328+ RNTupleAttrSetDescriptorBuilder &Name (std::string_view name)
1329+ {
1330+ fDesc .fName = name;
1331+ return *this ;
1332+ }
1333+ RNTupleAttrSetDescriptorBuilder &SchemaVersion (std::uint16_t major, std::uint16_t minor)
1334+ {
1335+ fDesc .fSchemaVersionMajor = major;
1336+ fDesc .fSchemaVersionMinor = minor;
1337+ return *this ;
1338+ }
1339+ RNTupleAttrSetDescriptorBuilder &AnchorLocator (const RNTupleLocator &loc)
1340+ {
1341+ fDesc .fAnchorLocator = loc;
1342+ return *this ;
1343+ }
1344+ RNTupleAttrSetDescriptorBuilder &AnchorLength (std::uint32_t length)
1345+ {
1346+ fDesc .fAnchorLength = length;
1347+ return *this ;
1348+ }
1349+
1350+ // / Attempt to make an AttributeSet descriptor. This may fail if the builder
1351+ // / was not given enough information to make a proper descriptor.
1352+ RResult<ROOT::Experimental::RNTupleAttrSetDescriptor> MoveDescriptor ();
1353+ };
1354+ } // namespace Experimental::Internal
1355+
12171356namespace Internal {
12181357
12191358// clang-format off
@@ -1597,6 +1736,8 @@ public:
15971736 RResult<void > AddExtraTypeInfo (RExtraTypeInfoDescriptor &&extraTypeInfoDesc);
15981737 void ReplaceExtraTypeInfo (RExtraTypeInfoDescriptor &&extraTypeInfoDesc);
15991738
1739+ RResult<void > AddAttributeSet (Experimental::RNTupleAttrSetDescriptor &&attrSetDesc);
1740+
16001741 // / Mark the beginning of the header extension; any fields and columns added after a call to this function are
16011742 // / annotated as begin part of the header extension.
16021743 void BeginHeaderExtension ();
@@ -1630,6 +1771,7 @@ inline RNTupleDescriptor CloneDescriptorSchema(const RNTupleDescriptor &desc)
16301771}
16311772
16321773} // namespace Internal
1774+
16331775} // namespace ROOT
16341776
16351777#endif // ROOT_RNTupleDescriptor
0 commit comments