Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleSerialize.cxx
Go to the documentation of this file.
1/// \file RNTupleSerialize.cxx
2/// \author Jakob Blomer <jblomer@cern.ch>
3/// \author Javier Lopez-Gomez <javier.lopez.gomez@cern.ch>
4/// \date 2021-08-02
5
6/*************************************************************************
7 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
15#include <ROOT/RError.hxx>
18#include <ROOT/RNTupleTypes.hxx>
19#include <ROOT/RNTupleUtils.hxx>
20#include <ROOT/BitUtils.hxx>
21
22#include <RVersion.h>
23#include <TBufferFile.h>
24#include <TClass.h>
25#include <TList.h>
26#include <TStreamerInfo.h>
28#include <xxhash.h>
29
30#include <cassert>
31#include <cmath>
32#include <cstring> // for memcpy
33#include <deque>
34#include <functional>
35#include <limits>
36#include <set>
37#include <unordered_map>
38
45
46namespace {
48
49ROOT::RResult<std::uint32_t> SerializeField(const ROOT::RFieldDescriptor &fieldDesc,
50 ROOT::DescriptorId_t onDiskParentId,
51 ROOT::DescriptorId_t onDiskProjectionSourceId, void *buffer)
52{
53
54 auto base = reinterpret_cast<unsigned char *>(buffer);
55 auto pos = base;
56 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
57
59
60 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetFieldVersion(), *where);
61 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetTypeVersion(), *where);
62 pos += RNTupleSerializer::SerializeUInt32(onDiskParentId, *where);
63 if (auto res = RNTupleSerializer::SerializeFieldStructure(fieldDesc.GetStructure(), *where)) {
64 pos += res.Unwrap();
65 } else {
66 return R__FORWARD_ERROR(res);
67 }
68
69 std::uint16_t flags = 0;
70 if (fieldDesc.GetNRepetitions() > 0)
72 if (fieldDesc.IsProjectedField())
74 if (fieldDesc.GetTypeChecksum().has_value())
76 if (fieldDesc.IsSoACollection())
78 pos += RNTupleSerializer::SerializeUInt16(flags, *where);
79
80 pos += RNTupleSerializer::SerializeString(fieldDesc.GetFieldName(), *where);
81 pos += RNTupleSerializer::SerializeString(fieldDesc.GetTypeName(), *where);
82 pos += RNTupleSerializer::SerializeString(fieldDesc.GetTypeAlias(), *where);
84
86 pos += RNTupleSerializer::SerializeUInt64(fieldDesc.GetNRepetitions(), *where);
87 }
89 pos += RNTupleSerializer::SerializeUInt32(onDiskProjectionSourceId, *where);
90 }
92 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetTypeChecksum().value(), *where);
93 }
94
95 auto size = pos - base;
97
98 return size;
99}
100
101// clang-format off
102/// Serialize, in order, fields enumerated in `fieldList` to `buffer`. `firstOnDiskId` specifies the on-disk ID for the
103/// first element in the `fieldList` sequence. Before calling this function `RContext::MapSchema()` should have been
104/// called on `context` in order to map in-memory field IDs to their on-disk counterpart.
105/// \return The number of bytes written to the output buffer; if `buffer` is `nullptr` no data is serialized and the
106/// required buffer size is returned
107// clang-format on
109SerializeFieldList(const ROOT::RNTupleDescriptor &desc, std::span<const ROOT::DescriptorId_t> fieldList,
110 std::size_t firstOnDiskId, const ROOT::Internal::RNTupleSerializer::RContext &context, void *buffer)
111{
112 auto base = reinterpret_cast<unsigned char *>(buffer);
113 auto pos = base;
114 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
115
116 auto fieldZeroId = desc.GetFieldZeroId();
117 ROOT::DescriptorId_t onDiskFieldId = firstOnDiskId;
118 for (auto fieldId : fieldList) {
119 const auto &f = desc.GetFieldDescriptor(fieldId);
120 auto onDiskParentId =
121 (f.GetParentId() == fieldZeroId) ? onDiskFieldId : context.GetOnDiskFieldId(f.GetParentId());
122 auto onDiskProjectionSourceId =
123 f.IsProjectedField() ? context.GetOnDiskFieldId(f.GetProjectionSourceId()) : ROOT::kInvalidDescriptorId;
124 if (auto res = SerializeField(f, onDiskParentId, onDiskProjectionSourceId, *where)) {
125 pos += res.Unwrap();
126 } else {
127 return R__FORWARD_ERROR(res);
128 }
129 ++onDiskFieldId;
130 }
131
132 return pos - base;
133}
134
136DeserializeField(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RFieldDescriptorBuilder &fieldDesc)
137{
138 using ENTupleStructure = ROOT::ENTupleStructure;
139
140 auto base = reinterpret_cast<const unsigned char *>(buffer);
141 auto bytes = base;
142 std::uint64_t frameSize;
143 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
144 if (auto res = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize)) {
145 bytes += res.Unwrap();
146 } else {
147 return R__FORWARD_ERROR(res);
148 }
149
150 std::uint32_t fieldVersion;
151 std::uint32_t typeVersion;
152 std::uint32_t parentId;
153 // initialize properly for call to SerializeFieldStructure()
154 ENTupleStructure structure{ENTupleStructure::kPlain};
155 std::uint16_t flags;
156 std::uint32_t result;
157 if (auto res = RNTupleSerializer::SerializeFieldStructure(structure, nullptr)) {
158 result = res.Unwrap();
159 } else {
160 return R__FORWARD_ERROR(res);
161 }
162 if (fnFrameSizeLeft() < 3 * sizeof(std::uint32_t) + result + sizeof(std::uint16_t)) {
163 return R__FAIL("field record frame too short");
164 }
168 if (auto res = RNTupleSerializer::DeserializeFieldStructure(bytes, structure)) {
169 bytes += res.Unwrap();
170 } else {
171 return R__FORWARD_ERROR(res);
172 }
174 fieldDesc.FieldVersion(fieldVersion).TypeVersion(typeVersion).ParentId(parentId).Structure(structure);
175
176 std::string fieldName;
177 std::string typeName;
178 std::string aliasName;
179 std::string description;
180 if (auto res = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), fieldName)) {
181 bytes += res.Unwrap();
182 } else {
183 return R__FORWARD_ERROR(res);
184 }
185 if (auto res = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), typeName)) {
186 bytes += res.Unwrap();
187 } else {
188 return R__FORWARD_ERROR(res);
189 }
190 if (auto res = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), aliasName)) {
191 bytes += res.Unwrap();
192 } else {
193 return R__FORWARD_ERROR(res);
194 }
195 if (auto res = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), description)) {
196 bytes += res.Unwrap();
197 } else {
198 return R__FORWARD_ERROR(res);
199 }
200 fieldDesc.FieldName(fieldName).TypeName(typeName).TypeAlias(aliasName).FieldDescription(description);
201
203 if (fnFrameSizeLeft() < sizeof(std::uint64_t))
204 return R__FAIL("field record frame too short");
205 std::uint64_t nRepetitions;
207 fieldDesc.NRepetitions(nRepetitions);
208 }
209
211 if (fnFrameSizeLeft() < sizeof(std::uint32_t))
212 return R__FAIL("field record frame too short");
213 std::uint32_t projectionSourceId;
214 bytes += RNTupleSerializer::DeserializeUInt32(bytes, projectionSourceId);
215 fieldDesc.ProjectionSourceId(projectionSourceId);
216 }
217
219 if (fnFrameSizeLeft() < sizeof(std::uint32_t))
220 return R__FAIL("field record frame too short");
221 std::uint32_t typeChecksum;
223 fieldDesc.TypeChecksum(typeChecksum);
224 }
225
227 fieldDesc.IsSoACollection(true);
228 }
229
230 return frameSize;
231}
232
233ROOT::RResult<std::uint32_t> SerializePhysicalColumn(const ROOT::RColumnDescriptor &columnDesc,
235 void *buffer)
236{
237 R__ASSERT(!columnDesc.IsAliasColumn());
238
239 auto base = reinterpret_cast<unsigned char *>(buffer);
240 auto pos = base;
241 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
242
244
245 if (auto res = RNTupleSerializer::SerializeColumnType(columnDesc.GetType(), *where)) {
246 pos += res.Unwrap();
247 } else {
248 return R__FORWARD_ERROR(res);
249 }
250 pos += RNTupleSerializer::SerializeUInt16(columnDesc.GetBitsOnStorage(), *where);
251 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskFieldId(columnDesc.GetFieldId()), *where);
252 std::uint16_t flags = 0;
253 if (columnDesc.IsDeferredColumn())
255 if (columnDesc.GetValueRange().has_value())
257 std::int64_t firstElementIdx = columnDesc.GetFirstElementIndex();
258 if (columnDesc.IsSuppressedDeferredColumn())
259 firstElementIdx = -firstElementIdx;
260 pos += RNTupleSerializer::SerializeUInt16(flags, *where);
263 pos += RNTupleSerializer::SerializeInt64(firstElementIdx, *where);
265 auto [min, max] = *columnDesc.GetValueRange();
266 std::uint64_t intMin, intMax;
267 static_assert(sizeof(min) == sizeof(intMin) && sizeof(max) == sizeof(intMax));
268 memcpy(&intMin, &min, sizeof(min));
269 memcpy(&intMax, &max, sizeof(max));
270 pos += RNTupleSerializer::SerializeUInt64(intMin, *where);
271 pos += RNTupleSerializer::SerializeUInt64(intMax, *where);
272 }
273
274 if (auto res = RNTupleSerializer::SerializeFramePostscript(buffer ? base : nullptr, pos - base)) {
275 pos += res.Unwrap();
276 } else {
277 return R__FORWARD_ERROR(res);
278 }
279
280 return pos - base;
281}
282
283ROOT::RResult<std::uint32_t> SerializeColumnsOfFields(const ROOT::RNTupleDescriptor &desc,
284 std::span<const ROOT::DescriptorId_t> fieldList,
286 void *buffer, bool forHeaderExtension)
287{
288 auto base = reinterpret_cast<unsigned char *>(buffer);
289 auto pos = base;
290 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
291
292 const auto *xHeader = !forHeaderExtension ? desc.GetHeaderExtension() : nullptr;
293
294 for (auto parentId : fieldList) {
295 // If we're serializing the non-extended header and we already have a header extension (which may happen if
296 // we load an RNTuple for incremental merging), we need to skip all the extended fields, as they need to be
297 // written in the header extension, not in the regular header.
298 if (xHeader && xHeader->ContainsField(parentId))
299 continue;
300
301 for (const auto &c : desc.GetColumnIterable(parentId)) {
302 if (c.IsAliasColumn() || (xHeader && xHeader->ContainsExtendedColumnRepresentation(c.GetLogicalId())))
303 continue;
304
305 if (auto res = SerializePhysicalColumn(c, context, *where)) {
306 pos += res.Unwrap();
307 } else {
308 return R__FORWARD_ERROR(res);
309 }
310 }
311 }
312
313 return pos - base;
314}
315
317DeserializeColumn(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RColumnDescriptorBuilder &columnDesc)
318{
320
321 auto base = reinterpret_cast<const unsigned char *>(buffer);
322 auto bytes = base;
323 std::uint64_t frameSize;
324 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
325 if (auto res = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize)) {
326 bytes += res.Unwrap();
327 } else {
328 return R__FORWARD_ERROR(res);
329 }
330
331 // Initialize properly for SerializeColumnType
332 ENTupleColumnType type{ENTupleColumnType::kIndex32};
333 std::uint16_t bitsOnStorage;
334 std::uint32_t fieldId;
335 std::uint16_t flags;
336 std::uint16_t representationIndex;
337 std::int64_t firstElementIdx = 0;
338 if (fnFrameSizeLeft() < RNTupleSerializer::SerializeColumnType(type, nullptr).Unwrap() + sizeof(std::uint16_t) +
339 2 * sizeof(std::uint32_t)) {
340 return R__FAIL("column record frame too short");
341 }
343 bytes += res.Unwrap();
344 } else {
345 return R__FORWARD_ERROR(res);
346 }
350 bytes += RNTupleSerializer::DeserializeUInt16(bytes, representationIndex);
352 if (fnFrameSizeLeft() < sizeof(std::uint64_t))
353 return R__FAIL("column record frame too short");
355 }
357 if (fnFrameSizeLeft() < 2 * sizeof(std::uint64_t))
358 return R__FAIL("field record frame too short");
359 std::uint64_t minInt, maxInt;
362 double min, max;
363 memcpy(&min, &minInt, sizeof(min));
364 memcpy(&max, &maxInt, sizeof(max));
365 columnDesc.ValueRange(min, max);
366 }
367
368 columnDesc.FieldId(fieldId).BitsOnStorage(bitsOnStorage).Type(type).RepresentationIndex(representationIndex);
369 columnDesc.FirstElementIndex(std::abs(firstElementIdx));
370 if (firstElementIdx < 0)
371 columnDesc.SetSuppressedDeferred();
372
373 return frameSize;
374}
375
376ROOT::RResult<std::uint32_t> SerializeExtraTypeInfo(const ROOT::RExtraTypeInfoDescriptor &desc, void *buffer)
377{
378 auto base = reinterpret_cast<unsigned char *>(buffer);
379 auto pos = base;
380 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
381
383
384 if (auto res = RNTupleSerializer::SerializeExtraTypeInfoId(desc.GetContentId(), *where)) {
385 pos += res.Unwrap();
386 } else {
387 return R__FORWARD_ERROR(res);
388 }
390 pos += RNTupleSerializer::SerializeString(desc.GetTypeName(), *where);
391 pos += RNTupleSerializer::SerializeString(desc.GetContent(), *where);
392
393 auto size = pos - base;
395
396 return size;
397}
398
399ROOT::RResult<std::uint32_t> SerializeExtraTypeInfoList(const ROOT::RNTupleDescriptor &ntplDesc, void *buffer)
400{
401 auto base = reinterpret_cast<unsigned char *>(buffer);
402 auto pos = base;
403 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
404
405 for (const auto &extraTypeInfoDesc : ntplDesc.GetExtraTypeInfoIterable()) {
406 if (auto res = SerializeExtraTypeInfo(extraTypeInfoDesc, *where)) {
407 pos += res.Unwrap();
408 } else {
409 return R__FORWARD_ERROR(res);
410 }
411 }
412
413 return pos - base;
414}
415
416ROOT::RResult<std::uint32_t> DeserializeExtraTypeInfo(const void *buffer, std::uint64_t bufSize,
418{
420
421 auto base = reinterpret_cast<const unsigned char *>(buffer);
422 auto bytes = base;
423 std::uint64_t frameSize;
424 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
425 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
426 if (!result)
427 return R__FORWARD_ERROR(result);
428 bytes += result.Unwrap();
429
430 EExtraTypeInfoIds contentId{EExtraTypeInfoIds::kInvalid};
431 std::uint32_t typeVersion;
432 if (fnFrameSizeLeft() < 2 * sizeof(std::uint32_t)) {
433 return R__FAIL("extra type info record frame too short");
434 }
436 if (!result)
437 return R__FORWARD_ERROR(result);
438 bytes += result.Unwrap();
440
441 std::string typeName;
442 std::string content;
443 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), typeName).Unwrap();
444 if (!result)
445 return R__FORWARD_ERROR(result);
446 bytes += result.Unwrap();
447 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), content).Unwrap();
448 if (!result)
449 return R__FORWARD_ERROR(result);
450 bytes += result.Unwrap();
451
452 desc.ContentId(contentId).TypeVersion(typeVersion).TypeName(typeName).Content(content);
453
454 return frameSize;
455}
456
457std::uint32_t SerializeLocatorPayloadLarge(const ROOT::RNTupleLocator &locator, unsigned char *buffer)
458{
459 if (buffer) {
461 RNTupleSerializer::SerializeUInt64(locator.GetPosition<std::uint64_t>(), buffer + sizeof(std::uint64_t));
462 }
463 return sizeof(std::uint64_t) + sizeof(std::uint64_t);
464}
465
466void DeserializeLocatorPayloadLarge(const unsigned char *buffer, ROOT::RNTupleLocator &locator)
467{
468 std::uint64_t nBytesOnStorage;
469 std::uint64_t position;
470 RNTupleSerializer::DeserializeUInt64(buffer, nBytesOnStorage);
471 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint64_t), position);
472 locator.SetNBytesOnStorage(nBytesOnStorage);
473 locator.SetPosition(position);
474}
475
476std::uint32_t SerializeLocatorPayloadObject64(const ROOT::RNTupleLocator &locator, unsigned char *buffer)
477{
478 const auto &data = locator.GetPosition<ROOT::RNTupleLocatorObject64>();
479 const uint32_t sizeofNBytesOnStorage = (locator.GetNBytesOnStorage() > std::numeric_limits<std::uint32_t>::max())
480 ? sizeof(std::uint64_t)
481 : sizeof(std::uint32_t);
482 if (buffer) {
483 if (sizeofNBytesOnStorage == sizeof(std::uint32_t)) {
485 } else {
487 }
488 RNTupleSerializer::SerializeUInt64(data.GetLocation(), buffer + sizeofNBytesOnStorage);
489 }
490 return sizeofNBytesOnStorage + sizeof(std::uint64_t);
491}
492
493ROOT::RResult<void> DeserializeLocatorPayloadObject64(const unsigned char *buffer, std::uint32_t sizeofLocatorPayload,
494 ROOT::RNTupleLocator &locator)
495{
496 std::uint64_t location;
497 if (sizeofLocatorPayload == 12) {
498 std::uint32_t nBytesOnStorage;
499 RNTupleSerializer::DeserializeUInt32(buffer, nBytesOnStorage);
500 locator.SetNBytesOnStorage(nBytesOnStorage);
501 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint32_t), location);
502 } else if (sizeofLocatorPayload == 16) {
503 std::uint64_t nBytesOnStorage;
504 RNTupleSerializer::DeserializeUInt64(buffer, nBytesOnStorage);
505 locator.SetNBytesOnStorage(nBytesOnStorage);
506 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint64_t), location);
507 } else {
508 return R__FAIL("invalid Object64 locator payload size: " + std::to_string(sizeofLocatorPayload));
509 }
510 locator.SetPosition(ROOT::RNTupleLocatorObject64{location});
512}
513
514std::uint32_t SerializeLocatorPayloadMulti(const ROOT::RNTupleLocator &locator, unsigned char *buffer)
515{
516 const auto &data = locator.GetPosition<ROOT::RNTupleLocatorMulti>();
517
518 void *bufferVoid = buffer;
519 auto base = buffer;
520 auto pos = base;
521 void **where = (buffer == nullptr) ? &bufferVoid : reinterpret_cast<void **>(&pos);
522
523 if (locator.GetNBytesOnStorage() > std::numeric_limits<std::uint32_t>::max()) {
524 pos += RNTupleSerializer::SerializeUInt64(locator.GetNBytesOnStorage(), *where);
525 } else {
526 pos += RNTupleSerializer::SerializeUInt32(locator.GetNBytesOnStorage(), *where);
527 }
528 pos += RNTupleSerializer::SerializeUInt32(data.GetObjectId(), *where);
529 pos += RNTupleSerializer::SerializeUInt32(data.GetOffset(), *where);
530
531 return pos - base;
532}
533
534ROOT::RResult<void> DeserializeLocatorPayloadMulti(const unsigned char *buffer, std::uint32_t sizeofLocatorPayload,
535 ROOT::RNTupleLocator &locator)
536{
537 const unsigned char *pos = buffer;
538 if (sizeofLocatorPayload == 12) {
539 std::uint32_t nBytesOnStorage;
540 pos += RNTupleSerializer::DeserializeUInt32(pos, nBytesOnStorage);
541 locator.SetNBytesOnStorage(nBytesOnStorage);
542 } else if (sizeofLocatorPayload == 16) {
543 std::uint64_t nBytesOnStorage;
544 pos += RNTupleSerializer::DeserializeUInt64(pos, nBytesOnStorage);
545 locator.SetNBytesOnStorage(nBytesOnStorage);
546 } else {
547 return R__FAIL("invalid Multi locator payload size: " + std::to_string(sizeofLocatorPayload));
548 }
549 std::uint32_t objectId;
550 std::uint32_t offset;
551 pos += RNTupleSerializer::DeserializeUInt32(pos, objectId);
553 locator.SetPosition(ROOT::RNTupleLocatorMulti(objectId, offset));
555}
556
557std::uint32_t SerializeAliasColumn(const ROOT::RColumnDescriptor &columnDesc,
558 const ROOT::Internal::RNTupleSerializer::RContext &context, void *buffer)
559{
560 R__ASSERT(columnDesc.IsAliasColumn());
561
562 auto base = reinterpret_cast<unsigned char *>(buffer);
563 auto pos = base;
564 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
565
567
568 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskColumnId(columnDesc.GetPhysicalId()), *where);
569 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskFieldId(columnDesc.GetFieldId()), *where);
570
571 pos += RNTupleSerializer::SerializeFramePostscript(buffer ? base : nullptr, pos - base).Unwrap();
572
573 return pos - base;
574}
575
576std::uint32_t SerializeAliasColumnsOfFields(const ROOT::RNTupleDescriptor &desc,
577 std::span<const ROOT::DescriptorId_t> fieldList,
578 const ROOT::Internal::RNTupleSerializer::RContext &context, void *buffer,
579 bool forHeaderExtension)
580{
581 auto base = reinterpret_cast<unsigned char *>(buffer);
582 auto pos = base;
583 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
584
585 const auto *xHeader = !forHeaderExtension ? desc.GetHeaderExtension() : nullptr;
586
587 for (auto parentId : fieldList) {
588 if (xHeader && xHeader->ContainsField(parentId))
589 continue;
590
591 for (const auto &c : desc.GetColumnIterable(parentId)) {
592 if (!c.IsAliasColumn() || (xHeader && xHeader->ContainsExtendedColumnRepresentation(c.GetLogicalId())))
593 continue;
594
595 pos += SerializeAliasColumn(c, context, *where);
596 }
597 }
598
599 return pos - base;
600}
601
602ROOT::RResult<std::uint32_t> DeserializeAliasColumn(const void *buffer, std::uint64_t bufSize,
603 std::uint32_t &physicalColumnId, std::uint32_t &fieldId)
604{
605 auto base = reinterpret_cast<const unsigned char *>(buffer);
606 auto bytes = base;
607 std::uint64_t frameSize;
608 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
609 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
610 if (!result)
611 return R__FORWARD_ERROR(result);
612 bytes += result.Unwrap();
613
614 if (fnFrameSizeLeft() < 2 * sizeof(std::uint32_t)) {
615 return R__FAIL("alias column record frame too short");
616 }
617
620
621 return frameSize;
622}
623
624} // anonymous namespace
625
626std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeXxHash3(const unsigned char *data, std::uint64_t length,
627 std::uint64_t &xxhash3, void *buffer)
628{
629 if (buffer != nullptr) {
630 xxhash3 = XXH3_64bits(data, length);
631 SerializeUInt64(xxhash3, buffer);
632 }
633 return 8;
634}
635
637 std::uint64_t &xxhash3)
638{
639 auto checksumReal = XXH3_64bits(data, length);
640 DeserializeUInt64(data + length, xxhash3);
641 if (xxhash3 != checksumReal)
642 return R__FAIL("XxHash-3 checksum mismatch");
643 return RResult<void>::Success();
644}
645
647{
648 std::uint64_t xxhash3;
649 return R__FORWARD_RESULT(VerifyXxHash3(data, length, xxhash3));
650}
651
652std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeInt16(std::int16_t val, void *buffer)
653{
654 if (buffer != nullptr) {
655 auto bytes = reinterpret_cast<unsigned char *>(buffer);
656 bytes[0] = (val & 0x00FF);
657 bytes[1] = (val & 0xFF00) >> 8;
658 }
659 return 2;
660}
661
662std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeInt16(const void *buffer, std::int16_t &val)
663{
664 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
665 val = std::int16_t(bytes[0]) + (std::int16_t(bytes[1]) << 8);
666 return 2;
667}
668
669std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeUInt16(std::uint16_t val, void *buffer)
670{
671 return SerializeInt16(val, buffer);
672}
673
674std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeUInt16(const void *buffer, std::uint16_t &val)
675{
676 return DeserializeInt16(buffer, *reinterpret_cast<std::int16_t *>(&val));
677}
678
679std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeInt32(std::int32_t val, void *buffer)
680{
681 if (buffer != nullptr) {
682 auto bytes = reinterpret_cast<unsigned char *>(buffer);
683 bytes[0] = (val & 0x000000FF);
684 bytes[1] = (val & 0x0000FF00) >> 8;
685 bytes[2] = (val & 0x00FF0000) >> 16;
686 bytes[3] = (val & 0xFF000000) >> 24;
687 }
688 return 4;
689}
690
691std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeInt32(const void *buffer, std::int32_t &val)
692{
693 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
694 val = std::int32_t(bytes[0]) + (std::int32_t(bytes[1]) << 8) + (std::int32_t(bytes[2]) << 16) +
695 (std::int32_t(bytes[3]) << 24);
696 return 4;
697}
698
699std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeUInt32(std::uint32_t val, void *buffer)
700{
701 return SerializeInt32(val, buffer);
702}
703
704std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeUInt32(const void *buffer, std::uint32_t &val)
705{
706 return DeserializeInt32(buffer, *reinterpret_cast<std::int32_t *>(&val));
707}
708
709std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeInt64(std::int64_t val, void *buffer)
710{
711 if (buffer != nullptr) {
712 auto bytes = reinterpret_cast<unsigned char *>(buffer);
713 bytes[0] = (val & 0x00000000000000FF);
714 bytes[1] = (val & 0x000000000000FF00) >> 8;
715 bytes[2] = (val & 0x0000000000FF0000) >> 16;
716 bytes[3] = (val & 0x00000000FF000000) >> 24;
717 bytes[4] = (val & 0x000000FF00000000) >> 32;
718 bytes[5] = (val & 0x0000FF0000000000) >> 40;
719 bytes[6] = (val & 0x00FF000000000000) >> 48;
720 bytes[7] = (val & 0xFF00000000000000) >> 56;
721 }
722 return 8;
723}
724
725std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeInt64(const void *buffer, std::int64_t &val)
726{
727 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
728 val = std::int64_t(bytes[0]) + (std::int64_t(bytes[1]) << 8) + (std::int64_t(bytes[2]) << 16) +
729 (std::int64_t(bytes[3]) << 24) + (std::int64_t(bytes[4]) << 32) + (std::int64_t(bytes[5]) << 40) +
730 (std::int64_t(bytes[6]) << 48) + (std::int64_t(bytes[7]) << 56);
731 return 8;
732}
733
734std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeUInt64(std::uint64_t val, void *buffer)
735{
736 return SerializeInt64(val, buffer);
737}
738
739std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeUInt64(const void *buffer, std::uint64_t &val)
740{
741 return DeserializeInt64(buffer, *reinterpret_cast<std::int64_t *>(&val));
742}
743
744std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeString(const std::string &val, void *buffer)
745{
746 if (buffer) {
747 auto pos = reinterpret_cast<unsigned char *>(buffer);
748 pos += SerializeUInt32(val.length(), pos);
749 memcpy(pos, val.data(), val.length());
750 }
751 return sizeof(std::uint32_t) + val.length();
752}
753
755ROOT::Internal::RNTupleSerializer::DeserializeString(const void *buffer, std::uint64_t bufSize, std::string &val)
756{
757 if (bufSize < sizeof(std::uint32_t))
758 return R__FAIL("string buffer too short");
759 bufSize -= sizeof(std::uint32_t);
760
761 auto base = reinterpret_cast<const unsigned char *>(buffer);
762 auto bytes = base;
763 std::uint32_t length;
764 bytes += DeserializeUInt32(buffer, length);
765 if (bufSize < length)
766 return R__FAIL("string buffer too short");
767
768 val.resize(length);
769 memcpy(&val[0], bytes, length);
770 return sizeof(std::uint32_t) + length;
771}
772
775{
776 switch (type) {
777 case ENTupleColumnType::kBit: return SerializeUInt16(0x00, buffer);
778 case ENTupleColumnType::kByte: return SerializeUInt16(0x01, buffer);
779 case ENTupleColumnType::kChar: return SerializeUInt16(0x02, buffer);
780 case ENTupleColumnType::kInt8: return SerializeUInt16(0x03, buffer);
781 case ENTupleColumnType::kUInt8: return SerializeUInt16(0x04, buffer);
782 case ENTupleColumnType::kInt16: return SerializeUInt16(0x05, buffer);
783 case ENTupleColumnType::kUInt16: return SerializeUInt16(0x06, buffer);
784 case ENTupleColumnType::kInt32: return SerializeUInt16(0x07, buffer);
785 case ENTupleColumnType::kUInt32: return SerializeUInt16(0x08, buffer);
786 case ENTupleColumnType::kInt64: return SerializeUInt16(0x09, buffer);
787 case ENTupleColumnType::kUInt64: return SerializeUInt16(0x0A, buffer);
788 case ENTupleColumnType::kReal16: return SerializeUInt16(0x0B, buffer);
789 case ENTupleColumnType::kReal32: return SerializeUInt16(0x0C, buffer);
790 case ENTupleColumnType::kReal64: return SerializeUInt16(0x0D, buffer);
791 case ENTupleColumnType::kIndex32: return SerializeUInt16(0x0E, buffer);
792 case ENTupleColumnType::kIndex64: return SerializeUInt16(0x0F, buffer);
793 case ENTupleColumnType::kSwitch: return SerializeUInt16(0x10, buffer);
794 case ENTupleColumnType::kSplitInt16: return SerializeUInt16(0x11, buffer);
795 case ENTupleColumnType::kSplitUInt16: return SerializeUInt16(0x12, buffer);
796 case ENTupleColumnType::kSplitInt32: return SerializeUInt16(0x13, buffer);
797 case ENTupleColumnType::kSplitUInt32: return SerializeUInt16(0x14, buffer);
798 case ENTupleColumnType::kSplitInt64: return SerializeUInt16(0x15, buffer);
799 case ENTupleColumnType::kSplitUInt64: return SerializeUInt16(0x16, buffer);
800 case ENTupleColumnType::kSplitReal32: return SerializeUInt16(0x18, buffer);
801 case ENTupleColumnType::kSplitReal64: return SerializeUInt16(0x19, buffer);
802 case ENTupleColumnType::kSplitIndex32: return SerializeUInt16(0x1A, buffer);
803 case ENTupleColumnType::kSplitIndex64: return SerializeUInt16(0x1B, buffer);
804 case ENTupleColumnType::kReal32Trunc: return SerializeUInt16(0x1C, buffer);
805 case ENTupleColumnType::kReal32Quant: return SerializeUInt16(0x1D, buffer);
806 default:
808 return SerializeUInt16(0x99, buffer);
809 return R__FAIL("unexpected column type");
810 }
811}
812
815{
816 std::uint16_t onDiskType;
817 auto result = DeserializeUInt16(buffer, onDiskType);
818
819 switch (onDiskType) {
820 case 0x00: type = ENTupleColumnType::kBit; break;
821 case 0x01: type = ENTupleColumnType::kByte; break;
822 case 0x02: type = ENTupleColumnType::kChar; break;
823 case 0x03: type = ENTupleColumnType::kInt8; break;
824 case 0x04: type = ENTupleColumnType::kUInt8; break;
825 case 0x05: type = ENTupleColumnType::kInt16; break;
826 case 0x06: type = ENTupleColumnType::kUInt16; break;
827 case 0x07: type = ENTupleColumnType::kInt32; break;
828 case 0x08: type = ENTupleColumnType::kUInt32; break;
829 case 0x09: type = ENTupleColumnType::kInt64; break;
830 case 0x0A: type = ENTupleColumnType::kUInt64; break;
831 case 0x0B: type = ENTupleColumnType::kReal16; break;
832 case 0x0C: type = ENTupleColumnType::kReal32; break;
833 case 0x0D: type = ENTupleColumnType::kReal64; break;
834 case 0x0E: type = ENTupleColumnType::kIndex32; break;
835 case 0x0F: type = ENTupleColumnType::kIndex64; break;
836 case 0x10: type = ENTupleColumnType::kSwitch; break;
837 case 0x11: type = ENTupleColumnType::kSplitInt16; break;
838 case 0x12: type = ENTupleColumnType::kSplitUInt16; break;
839 case 0x13: type = ENTupleColumnType::kSplitInt32; break;
840 case 0x14: type = ENTupleColumnType::kSplitUInt32; break;
841 case 0x15: type = ENTupleColumnType::kSplitInt64; break;
842 case 0x16: type = ENTupleColumnType::kSplitUInt64; break;
843 case 0x18: type = ENTupleColumnType::kSplitReal32; break;
844 case 0x19: type = ENTupleColumnType::kSplitReal64; break;
845 case 0x1A: type = ENTupleColumnType::kSplitIndex32; break;
846 case 0x1B: type = ENTupleColumnType::kSplitIndex64; break;
847 case 0x1C: type = ENTupleColumnType::kReal32Trunc; break;
848 case 0x1D: type = ENTupleColumnType::kReal32Quant; break;
849 // case 0x99 => kTestFutureColumnType missing on purpose
850 default:
851 // may be a column type introduced by a future version
853 break;
854 }
855 return result;
856}
857
860{
862 switch (structure) {
863 case ENTupleStructure::kPlain: return SerializeUInt16(0x00, buffer);
864 case ENTupleStructure::kCollection: return SerializeUInt16(0x01, buffer);
865 case ENTupleStructure::kRecord: return SerializeUInt16(0x02, buffer);
866 case ENTupleStructure::kVariant: return SerializeUInt16(0x03, buffer);
867 case ENTupleStructure::kStreamer: return SerializeUInt16(0x04, buffer);
868 default:
870 return SerializeUInt16(0x99, buffer);
871 return R__FAIL("unexpected field structure type");
872 }
873}
874
877{
879 std::uint16_t onDiskValue;
880 auto result = DeserializeUInt16(buffer, onDiskValue);
881 switch (onDiskValue) {
882 case 0x00: structure = ENTupleStructure::kPlain; break;
883 case 0x01: structure = ENTupleStructure::kCollection; break;
884 case 0x02: structure = ENTupleStructure::kRecord; break;
885 case 0x03: structure = ENTupleStructure::kVariant; break;
886 case 0x04: structure = ENTupleStructure::kStreamer; break;
887 // case 0x99 => kTestFutureFieldStructure intentionally missing
888 default: structure = ENTupleStructure::kUnknown;
889 }
890 return result;
891}
892
895{
896 switch (id) {
898 default: return R__FAIL("unexpected extra type info id");
899 }
900}
901
904{
905 std::uint32_t onDiskValue;
906 auto result = DeserializeUInt32(buffer, onDiskValue);
907 switch (onDiskValue) {
908 case 0x00: id = ROOT::EExtraTypeInfoIds::kStreamerInfo; break;
909 default:
911 R__LOG_DEBUG(0, ROOT::Internal::NTupleLog()) << "Unknown extra type info id: " << onDiskValue;
912 }
913 return result;
914}
915
916std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeEnvelopePreamble(std::uint16_t envelopeType, void *buffer)
917{
918 auto base = reinterpret_cast<unsigned char *>(buffer);
919 auto pos = base;
920 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
921
922 pos += SerializeUInt64(envelopeType, *where);
923 // The 48bits size information is filled in the postscript
924 return pos - base;
925}
926
928 std::uint64_t size,
929 std::uint64_t &xxhash3)
930{
931 if (size < sizeof(std::uint64_t))
932 return R__FAIL("envelope size too small");
933 if (size >= static_cast<uint64_t>(1) << 48)
934 return R__FAIL("envelope size too big");
935 if (envelope) {
936 std::uint64_t typeAndSize;
937 DeserializeUInt64(envelope, typeAndSize);
938 typeAndSize |= (size + 8) << 16;
939 SerializeUInt64(typeAndSize, envelope);
940 }
941 return SerializeXxHash3(envelope, size, xxhash3, envelope ? (envelope + size) : nullptr);
942}
943
946{
947 std::uint64_t xxhash3;
948 return R__FORWARD_RESULT(SerializeEnvelopePostscript(envelope, size, xxhash3));
949}
950
952ROOT::Internal::RNTupleSerializer::DeserializeEnvelope(const void *buffer, std::uint64_t bufSize,
953 std::uint16_t expectedType, std::uint64_t &xxhash3)
954{
955 const std::uint64_t minEnvelopeSize = sizeof(std::uint64_t) + sizeof(std::uint64_t);
956 if (bufSize < minEnvelopeSize)
957 return R__FAIL("invalid envelope buffer, too short");
958
959 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
960 auto base = bytes;
961
962 std::uint64_t typeAndSize;
963 bytes += DeserializeUInt64(bytes, typeAndSize);
964
965 std::uint16_t envelopeType = typeAndSize & 0xFFFF;
966 if (envelopeType != expectedType) {
967 return R__FAIL("envelope type mismatch: expected " + std::to_string(expectedType) + ", found " +
968 std::to_string(envelopeType));
969 }
970
971 std::uint64_t envelopeSize = typeAndSize >> 16;
972 if (bufSize < envelopeSize)
973 return R__FAIL("envelope buffer size too small");
974 if (envelopeSize < minEnvelopeSize)
975 return R__FAIL("invalid envelope, too short");
976
977 auto result = VerifyXxHash3(base, envelopeSize - 8, xxhash3);
978 if (!result)
979 return R__FORWARD_ERROR(result);
980
981 return sizeof(typeAndSize);
982}
983
985 std::uint64_t bufSize,
986 std::uint16_t expectedType)
987{
988 std::uint64_t xxhash3;
989 return R__FORWARD_RESULT(DeserializeEnvelope(buffer, bufSize, expectedType, xxhash3));
990}
991
993{
994 // Marker: multiply the final size with 1
995 return SerializeInt64(1, buffer);
996}
997
999{
1000 auto base = reinterpret_cast<unsigned char *>(buffer);
1001 auto pos = base;
1002 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1003
1004 // Marker: multiply the final size with -1
1005 pos += SerializeInt64(-1, *where);
1006 pos += SerializeUInt32(nitems, *where);
1007 return pos - base;
1008}
1009
1012{
1013 auto preambleSize = sizeof(std::int64_t);
1014 if (size < preambleSize)
1015 return R__FAIL("frame too short: " + std::to_string(size));
1016 if (frame) {
1017 std::int64_t marker;
1018 DeserializeInt64(frame, marker);
1019 if ((marker < 0) && (size < (sizeof(std::uint32_t) + preambleSize)))
1020 return R__FAIL("frame too short: " + std::to_string(size));
1021 SerializeInt64(marker * static_cast<int64_t>(size), frame);
1022 }
1023 return 0;
1024}
1025
1027ROOT::Internal::RNTupleSerializer::DeserializeFrameHeader(const void *buffer, std::uint64_t bufSize,
1028 std::uint64_t &frameSize, std::uint32_t &nitems)
1029{
1030 std::uint64_t minSize = sizeof(std::int64_t);
1031 if (bufSize < minSize)
1032 return R__FAIL("frame too short");
1033
1034 std::int64_t *ssize = reinterpret_cast<std::int64_t *>(&frameSize);
1035 DeserializeInt64(buffer, *ssize);
1036
1037 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1038 bytes += minSize;
1039
1040 if (*ssize >= 0) {
1041 // Record frame
1042 nitems = 1;
1043 } else {
1044 // List frame
1045 minSize += sizeof(std::uint32_t);
1046 if (bufSize < minSize)
1047 return R__FAIL("frame too short");
1049 *ssize = -(*ssize);
1050 }
1051
1052 if (frameSize < minSize)
1053 return R__FAIL("corrupt frame size");
1054 if (bufSize < frameSize)
1055 return R__FAIL("frame too short");
1056
1057 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1058}
1059
1061 std::uint64_t bufSize,
1062 std::uint64_t &frameSize)
1063{
1064 std::uint32_t nitems;
1065 return R__FORWARD_RESULT(DeserializeFrameHeader(buffer, bufSize, frameSize, nitems));
1066}
1067
1069ROOT::Internal::RNTupleSerializer::SerializeFeatureFlags(const std::vector<std::uint64_t> &flags, void *buffer)
1070{
1071 if (flags.empty())
1072 return SerializeUInt64(0, buffer);
1073
1074 if (buffer) {
1075 auto bytes = reinterpret_cast<unsigned char *>(buffer);
1076
1077 for (unsigned i = 0; i < flags.size(); ++i) {
1078 if (flags[i] & 0x8000000000000000)
1079 return R__FAIL("feature flag out of bounds");
1080
1081 // The MSb indicates that another Int64 follows; set this bit to 1 for all except the last element
1082 if (i == (flags.size() - 1))
1083 SerializeUInt64(flags[i], bytes);
1084 else
1085 bytes += SerializeUInt64(flags[i] | 0x8000000000000000, bytes);
1086 }
1087 }
1088 return (flags.size() * sizeof(std::int64_t));
1089}
1090
1092ROOT::Internal::RNTupleSerializer::DeserializeFeatureFlags(const void *buffer, std::uint64_t bufSize,
1093 std::vector<std::uint64_t> &flags)
1094{
1095 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1096
1097 flags.clear();
1098 std::uint64_t f;
1099 do {
1100 if (bufSize < sizeof(std::uint64_t))
1101 return R__FAIL("feature flag buffer too short");
1103 bufSize -= sizeof(std::uint64_t);
1104 flags.emplace_back(f & ~0x8000000000000000);
1105 } while (f & 0x8000000000000000);
1106
1107 return (flags.size() * sizeof(std::uint64_t));
1108}
1109
1112{
1114 return R__FAIL("locator is not serializable");
1115
1116 std::uint32_t size = 0;
1117 if ((locator.GetType() == RNTupleLocator::kTypeFile) &&
1118 (locator.GetNBytesOnStorage() <= std::numeric_limits<std::int32_t>::max())) {
1119 size += SerializeUInt32(locator.GetNBytesOnStorage(), buffer);
1120 size += SerializeUInt64(locator.GetPosition<std::uint64_t>(),
1121 buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
1122 return size;
1123 }
1124
1125 std::uint8_t locatorType = 0;
1126 auto payloadp = buffer ? reinterpret_cast<unsigned char *>(buffer) + sizeof(std::int32_t) : nullptr;
1127 switch (locator.GetType()) {
1129 size += SerializeLocatorPayloadLarge(locator, payloadp);
1130 locatorType = 0x01;
1131 break;
1133 size += SerializeLocatorPayloadObject64(locator, payloadp);
1134 locatorType = 0x02;
1135 break;
1137 size += SerializeLocatorPayloadMulti(locator, payloadp);
1138 locatorType = 0x03;
1139 break;
1140 default:
1141 if (locator.GetType() == ROOT::Internal::kTestLocatorType) {
1142 // For the testing locator, use the same payload format as Object64. We won't read it back anyway.
1143 RNTupleLocator dummy;
1145 size += SerializeLocatorPayloadObject64(dummy, payloadp);
1146 locatorType = 0x7e;
1147 } else {
1148 return R__FAIL("locator has unknown type");
1149 }
1150 }
1151 std::int32_t head = sizeof(std::int32_t) + size;
1152 head |= locator.GetReserved() << 16;
1153 head |= static_cast<int>(locatorType & 0x7F) << 24;
1154 head = -head;
1155 size += RNTupleSerializer::SerializeInt32(head, buffer);
1156 return size;
1157}
1158
1160 std::uint64_t bufSize,
1161 RNTupleLocator &locator)
1162{
1163 if (bufSize < sizeof(std::int32_t))
1164 return R__FAIL("too short locator");
1165
1166 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1167 std::int32_t head;
1168
1169 bytes += DeserializeInt32(bytes, head);
1170 bufSize -= sizeof(std::int32_t);
1171 if (head < 0) {
1172 head = -head;
1173 const int type = head >> 24;
1174 const std::uint32_t payloadSize = (static_cast<std::uint32_t>(head) & 0x0000FFFF) - sizeof(std::int32_t);
1175 if (bufSize < payloadSize)
1176 return R__FAIL("too short locator");
1177
1178 locator.SetReserved(static_cast<std::uint32_t>(head >> 16) & 0xFF);
1179 switch (type) {
1180 case 0x01:
1182 DeserializeLocatorPayloadLarge(bytes, locator);
1183 break;
1184 case 0x02: {
1186 auto res = DeserializeLocatorPayloadObject64(bytes, payloadSize, locator);
1187 if (!res)
1188 return R__FORWARD_ERROR(res);
1189 break;
1190 }
1191 case 0x03: {
1193 auto res = DeserializeLocatorPayloadMulti(bytes, payloadSize, locator);
1194 if (!res)
1195 return R__FORWARD_ERROR(res);
1196 break;
1197 }
1198 default: locator.SetType(RNTupleLocator::kTypeUnknown);
1199 }
1200 bytes += payloadSize;
1201 } else {
1202 if (bufSize < sizeof(std::uint64_t))
1203 return R__FAIL("too short locator");
1204 std::uint64_t offset;
1207 locator.SetNBytesOnStorage(head);
1208 locator.SetPosition(offset);
1209 }
1210
1211 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1212}
1213
1216{
1217 auto size = SerializeUInt64(envelopeLink.fLength, buffer);
1218 auto res =
1219 SerializeLocator(envelopeLink.fLocator, buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
1220 if (res)
1221 size += res.Unwrap();
1222 else
1223 return R__FORWARD_ERROR(res);
1224 return size;
1225}
1226
1228 std::uint64_t bufSize,
1229 REnvelopeLink &envelopeLink)
1230{
1231 if (bufSize < sizeof(std::int64_t))
1232 return R__FAIL("too short envelope link");
1233
1234 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1235 bytes += DeserializeUInt64(bytes, envelopeLink.fLength);
1236 bufSize -= sizeof(std::uint64_t);
1237 if (auto res = DeserializeLocator(bytes, bufSize, envelopeLink.fLocator)) {
1238 bytes += res.Unwrap();
1239 } else {
1240 return R__FORWARD_ERROR(res);
1241 }
1242 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1243}
1244
1247{
1248 if (clusterSummary.fNEntries >= (static_cast<std::uint64_t>(1) << 56)) {
1249 return R__FAIL("number of entries in cluster exceeds maximum of 2^56");
1250 }
1251
1252 auto base = reinterpret_cast<unsigned char *>(buffer);
1253 auto pos = base;
1254 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1255
1256 auto frame = pos;
1257 pos += SerializeRecordFramePreamble(*where);
1258 pos += SerializeUInt64(clusterSummary.fFirstEntry, *where);
1259 const std::uint64_t nEntriesAndFlags =
1260 (static_cast<std::uint64_t>(clusterSummary.fFlags) << 56) | clusterSummary.fNEntries;
1261 pos += SerializeUInt64(nEntriesAndFlags, *where);
1262
1263 auto size = pos - frame;
1264 if (auto res = SerializeFramePostscript(frame, size)) {
1265 pos += res.Unwrap();
1266 } else {
1267 return R__FORWARD_ERROR(res);
1268 }
1269 return size;
1270}
1271
1274 RClusterSummary &clusterSummary)
1275{
1276 auto base = reinterpret_cast<const unsigned char *>(buffer);
1277 auto bytes = base;
1278 std::uint64_t frameSize;
1279 if (auto res = DeserializeFrameHeader(bytes, bufSize, frameSize)) {
1280 bytes += res.Unwrap();
1281 } else {
1282 return R__FORWARD_ERROR(res);
1283 }
1284
1285 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
1286 if (fnFrameSizeLeft() < 2 * sizeof(std::uint64_t))
1287 return R__FAIL("too short cluster summary");
1288
1289 bytes += DeserializeUInt64(bytes, clusterSummary.fFirstEntry);
1290 std::uint64_t nEntriesAndFlags;
1291 bytes += DeserializeUInt64(bytes, nEntriesAndFlags);
1292
1293 const std::uint64_t nEntries = (nEntriesAndFlags << 8) >> 8;
1294 const std::uint8_t flags = nEntriesAndFlags >> 56;
1295
1296 if (flags & 0x01) {
1297 return R__FAIL("sharded cluster flag set in cluster summary; sharded clusters are currently unsupported.");
1298 }
1299
1300 clusterSummary.fNEntries = nEntries;
1301 clusterSummary.fFlags = flags;
1302
1303 return frameSize;
1304}
1305
1308{
1309 auto base = reinterpret_cast<unsigned char *>(buffer);
1310 auto pos = base;
1311 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1312
1313 auto frame = pos;
1314 pos += SerializeRecordFramePreamble(*where);
1315 pos += SerializeUInt64(clusterGroup.fMinEntry, *where);
1316 pos += SerializeUInt64(clusterGroup.fEntrySpan, *where);
1317 pos += SerializeUInt32(clusterGroup.fNClusters, *where);
1318 if (auto res = SerializeEnvelopeLink(clusterGroup.fPageListEnvelopeLink, *where)) {
1319 pos += res.Unwrap();
1320 } else {
1321 return R__FORWARD_ERROR(res);
1322 }
1323 auto size = pos - frame;
1324 if (auto res = SerializeFramePostscript(frame, size)) {
1325 return size;
1326 } else {
1327 return R__FORWARD_ERROR(res);
1328 }
1329}
1330
1332 std::uint64_t bufSize,
1333 RClusterGroup &clusterGroup)
1334{
1335 auto base = reinterpret_cast<const unsigned char *>(buffer);
1336 auto bytes = base;
1337
1338 std::uint64_t frameSize;
1339 if (auto res = DeserializeFrameHeader(bytes, bufSize, frameSize)) {
1340 bytes += res.Unwrap();
1341 } else {
1342 return R__FORWARD_ERROR(res);
1343 }
1344
1345 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
1346 if (fnFrameSizeLeft() < sizeof(std::uint32_t) + 2 * sizeof(std::uint64_t))
1347 return R__FAIL("too short cluster group");
1348
1349 bytes += DeserializeUInt64(bytes, clusterGroup.fMinEntry);
1350 bytes += DeserializeUInt64(bytes, clusterGroup.fEntrySpan);
1351 bytes += DeserializeUInt32(bytes, clusterGroup.fNClusters);
1352 if (auto res = DeserializeEnvelopeLink(bytes, fnFrameSizeLeft(), clusterGroup.fPageListEnvelopeLink)) {
1353 bytes += res.Unwrap();
1354 } else {
1355 return R__FORWARD_ERROR(res);
1356 }
1357
1358 return frameSize;
1359}
1360
1362 bool forHeaderExtension)
1363{
1364 auto fieldZeroId = desc.GetFieldZeroId();
1365 auto depthFirstTraversal = [&](std::span<ROOT::DescriptorId_t> fieldTrees, auto doForEachField) {
1366 std::deque<ROOT::DescriptorId_t> idQueue{fieldTrees.begin(), fieldTrees.end()};
1367 while (!idQueue.empty()) {
1368 auto fieldId = idQueue.front();
1369 idQueue.pop_front();
1370 // Field zero has no physical representation nor columns of its own; recurse over its subfields only
1371 if (fieldId != fieldZeroId)
1372 doForEachField(fieldId);
1373 unsigned i = 0;
1374 for (const auto &f : desc.GetFieldIterable(fieldId))
1375 idQueue.insert(idQueue.begin() + i++, f.GetId());
1376 }
1377 };
1378
1379 R__ASSERT(desc.GetNFields() > 0); // we must have at least a zero field
1380
1381 std::vector<ROOT::DescriptorId_t> fieldTrees;
1382 if (!forHeaderExtension) {
1383 fieldTrees.emplace_back(fieldZeroId);
1384 } else if (auto xHeader = desc.GetHeaderExtension()) {
1385 fieldTrees = xHeader->GetTopMostFields(desc);
1386 }
1387 depthFirstTraversal(fieldTrees, [&](ROOT::DescriptorId_t fieldId) { MapFieldId(fieldId); });
1388 depthFirstTraversal(fieldTrees, [&](ROOT::DescriptorId_t fieldId) {
1389 for (const auto &c : desc.GetColumnIterable(fieldId)) {
1390 if (!c.IsAliasColumn()) {
1391 MapPhysicalColumnId(c.GetPhysicalId());
1392 }
1393 }
1394 });
1395
1396 if (forHeaderExtension) {
1397 // Create physical IDs for column representations that extend fields of the regular header.
1398 // First the physical columns then the alias columns.
1399 for (auto memId : desc.GetHeaderExtension()->GetExtendedColumnRepresentations()) {
1400 const auto &columnDesc = desc.GetColumnDescriptor(memId);
1401 if (!columnDesc.IsAliasColumn()) {
1402 MapPhysicalColumnId(columnDesc.GetPhysicalId());
1403 }
1404 }
1405 }
1406}
1407
1410 const RContext &context, bool forHeaderExtension)
1411{
1412 auto base = reinterpret_cast<unsigned char *>(buffer);
1413 auto pos = base;
1414 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1415
1416 std::size_t nFields = 0, nColumns = 0, nAliasColumns = 0, fieldListOffset = 0;
1417 // Columns in the extension header that are attached to a field of the regular header
1418 std::vector<std::reference_wrapper<const ROOT::RColumnDescriptor>> extraColumns;
1419 if (forHeaderExtension) {
1420 // A call to `RNTupleDescriptorBuilder::BeginHeaderExtension()` is not strictly required after serializing the
1421 // header, which may happen, e.g., in unit tests. Ensure an empty schema extension is serialized in this case
1422 if (auto xHeader = desc.GetHeaderExtension()) {
1423 nFields = xHeader->GetNFields();
1424 nColumns = xHeader->GetNPhysicalColumns();
1425 nAliasColumns = xHeader->GetNLogicalColumns() - xHeader->GetNPhysicalColumns();
1426 fieldListOffset = desc.GetNFields() - nFields - 1;
1427
1428 extraColumns.reserve(xHeader->GetExtendedColumnRepresentations().size());
1429 for (auto columnId : xHeader->GetExtendedColumnRepresentations()) {
1430 extraColumns.emplace_back(desc.GetColumnDescriptor(columnId));
1431 }
1432 }
1433 } else {
1434 if (auto xHeader = desc.GetHeaderExtension()) {
1435 nFields = desc.GetNFields() - xHeader->GetNFields() - 1;
1436 nColumns = desc.GetNPhysicalColumns() - xHeader->GetNPhysicalColumns();
1437 nAliasColumns = desc.GetNLogicalColumns() - desc.GetNPhysicalColumns() -
1438 (xHeader->GetNLogicalColumns() - xHeader->GetNPhysicalColumns());
1439 } else {
1440 nFields = desc.GetNFields() - 1;
1441 nColumns = desc.GetNPhysicalColumns();
1442 nAliasColumns = desc.GetNLogicalColumns() - desc.GetNPhysicalColumns();
1443 }
1444 }
1445 const auto nExtraTypeInfos = desc.GetNExtraTypeInfos();
1446 const auto &onDiskFields = context.GetOnDiskFieldList();
1447 R__ASSERT(onDiskFields.size() >= fieldListOffset);
1448 std::span<const ROOT::DescriptorId_t> fieldList{onDiskFields.data() + fieldListOffset, nFields};
1449
1450 auto frame = pos;
1451 pos += SerializeListFramePreamble(nFields, *where);
1452 if (auto res = SerializeFieldList(desc, fieldList, /*firstOnDiskId=*/fieldListOffset, context, *where)) {
1453 pos += res.Unwrap();
1454 } else {
1455 return R__FORWARD_ERROR(res);
1456 }
1457 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1458 pos += res.Unwrap();
1459 } else {
1460 return R__FORWARD_ERROR(res);
1461 }
1462
1463 frame = pos;
1464 pos += SerializeListFramePreamble(nColumns, *where);
1465 if (auto res = SerializeColumnsOfFields(desc, fieldList, context, *where, forHeaderExtension)) {
1466 pos += res.Unwrap();
1467 } else {
1468 return R__FORWARD_ERROR(res);
1469 }
1470 for (const auto &c : extraColumns) {
1471 if (!c.get().IsAliasColumn()) {
1472 if (auto res = SerializePhysicalColumn(c.get(), context, *where)) {
1473 pos += res.Unwrap();
1474 } else {
1475 return R__FORWARD_ERROR(res);
1476 }
1477 }
1478 }
1479 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1480 pos += res.Unwrap();
1481 } else {
1482 return R__FORWARD_ERROR(res);
1483 }
1484
1485 frame = pos;
1486 pos += SerializeListFramePreamble(nAliasColumns, *where);
1487 pos += SerializeAliasColumnsOfFields(desc, fieldList, context, *where, forHeaderExtension);
1488 for (const auto &c : extraColumns) {
1489 if (c.get().IsAliasColumn()) {
1490 pos += SerializeAliasColumn(c.get(), context, *where);
1491 }
1492 }
1493 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1494 pos += res.Unwrap();
1495 } else {
1496 return R__FORWARD_ERROR(res);
1497 }
1498
1499 frame = pos;
1500 // We only serialize the extra type info list in the header extension.
1501 if (forHeaderExtension) {
1502 pos += SerializeListFramePreamble(nExtraTypeInfos, *where);
1503 if (auto res = SerializeExtraTypeInfoList(desc, *where)) {
1504 pos += res.Unwrap();
1505 } else {
1506 return R__FORWARD_ERROR(res);
1507 }
1508 } else {
1509 pos += SerializeListFramePreamble(0, *where);
1510 }
1511 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1512 pos += res.Unwrap();
1513 } else {
1514 return R__FORWARD_ERROR(res);
1515 }
1516
1517 return static_cast<std::uint32_t>(pos - base);
1518}
1519
1522 RNTupleDescriptorBuilder &descBuilder)
1523{
1524 auto base = reinterpret_cast<const unsigned char *>(buffer);
1525 auto bytes = base;
1526 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1527
1528 std::uint64_t frameSize;
1529 auto frame = bytes;
1530 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
1531
1532 std::uint32_t nFields;
1533 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nFields)) {
1534 bytes += res.Unwrap();
1535 } else {
1536 return R__FORWARD_ERROR(res);
1537 }
1538 // The zero field is always added before `DeserializeSchemaDescription()` is called
1539 const std::uint32_t fieldIdRangeBegin = descBuilder.GetDescriptor().GetNFields() - 1;
1540 for (unsigned i = 0; i < nFields; ++i) {
1541 std::uint32_t fieldId = fieldIdRangeBegin + i;
1542 RFieldDescriptorBuilder fieldBuilder;
1543 if (auto res = DeserializeField(bytes, fnFrameSizeLeft(), fieldBuilder)) {
1544 bytes += res.Unwrap();
1545 } else {
1546 return R__FORWARD_ERROR(res);
1547 }
1548 if (fieldId == fieldBuilder.GetParentId())
1549 fieldBuilder.ParentId(kZeroFieldId);
1550 auto fieldDesc = fieldBuilder.FieldId(fieldId).MakeDescriptor();
1551 if (!fieldDesc)
1552 return R__FORWARD_ERROR(fieldDesc);
1553 const auto parentId = fieldDesc.Inspect().GetParentId();
1554 const auto projectionSourceId = fieldDesc.Inspect().GetProjectionSourceId();
1555 descBuilder.AddField(fieldDesc.Unwrap());
1556 auto resVoid = descBuilder.AddFieldLink(parentId, fieldId);
1557 if (!resVoid)
1558 return R__FORWARD_ERROR(resVoid);
1559 if (projectionSourceId != ROOT::kInvalidDescriptorId) {
1560 resVoid = descBuilder.AddFieldProjection(projectionSourceId, fieldId);
1561 if (!resVoid)
1562 return R__FORWARD_ERROR(resVoid);
1563 }
1564 }
1565 bytes = frame + frameSize;
1566
1567 // As columns are added in order of representation index and column index, determine the column index
1568 // for the currently deserialized column from the columns already added.
1569 auto fnNextColumnIndex = [&descBuilder](ROOT::DescriptorId_t fieldId,
1570 std::uint16_t representationIndex) -> std::uint32_t {
1571 const auto &existingColumns = descBuilder.GetDescriptor().GetFieldDescriptor(fieldId).GetLogicalColumnIds();
1572 if (existingColumns.empty())
1573 return 0;
1574 const auto &lastColumnDesc = descBuilder.GetDescriptor().GetColumnDescriptor(existingColumns.back());
1575 return (representationIndex == lastColumnDesc.GetRepresentationIndex()) ? (lastColumnDesc.GetIndex() + 1) : 0;
1576 };
1577
1578 std::uint32_t nColumns;
1579 frame = bytes;
1580 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nColumns)) {
1581 bytes += res.Unwrap();
1582 } else {
1583 return R__FORWARD_ERROR(res);
1584 }
1585
1586 if (descBuilder.GetDescriptor().GetNLogicalColumns() > descBuilder.GetDescriptor().GetNPhysicalColumns())
1587 descBuilder.ShiftAliasColumns(nColumns);
1588
1589 const std::uint32_t columnIdRangeBegin = descBuilder.GetDescriptor().GetNPhysicalColumns();
1590 for (unsigned i = 0; i < nColumns; ++i) {
1591 std::uint32_t columnId = columnIdRangeBegin + i;
1592 RColumnDescriptorBuilder columnBuilder;
1593 if (auto res = DeserializeColumn(bytes, fnFrameSizeLeft(), columnBuilder)) {
1594 bytes += res.Unwrap();
1595 } else {
1596 return R__FORWARD_ERROR(res);
1597 }
1598
1599 columnBuilder.Index(fnNextColumnIndex(columnBuilder.GetFieldId(), columnBuilder.GetRepresentationIndex()));
1600 columnBuilder.LogicalColumnId(columnId);
1601 columnBuilder.PhysicalColumnId(columnId);
1602 auto columnDesc = columnBuilder.MakeDescriptor();
1603 if (!columnDesc)
1604 return R__FORWARD_ERROR(columnDesc);
1605 auto resVoid = descBuilder.AddColumn(columnDesc.Unwrap());
1606 if (!resVoid)
1607 return R__FORWARD_ERROR(resVoid);
1608 }
1609 bytes = frame + frameSize;
1610
1611 std::uint32_t nAliasColumns;
1612 frame = bytes;
1613 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nAliasColumns)) {
1614 bytes += res.Unwrap();
1615 } else {
1616 return R__FORWARD_ERROR(res);
1617 }
1618 const std::uint32_t aliasColumnIdRangeBegin = descBuilder.GetDescriptor().GetNLogicalColumns();
1619 for (unsigned i = 0; i < nAliasColumns; ++i) {
1620 std::uint32_t physicalId;
1621 std::uint32_t fieldId;
1622 if (auto res = DeserializeAliasColumn(bytes, fnFrameSizeLeft(), physicalId, fieldId)) {
1623 bytes += res.Unwrap();
1624 } else {
1625 return R__FORWARD_ERROR(res);
1626 }
1627
1628 RColumnDescriptorBuilder columnBuilder;
1629 columnBuilder.LogicalColumnId(aliasColumnIdRangeBegin + i).PhysicalColumnId(physicalId).FieldId(fieldId);
1630 const auto &physicalColumnDesc = descBuilder.GetDescriptor().GetColumnDescriptor(physicalId);
1631 columnBuilder.BitsOnStorage(physicalColumnDesc.GetBitsOnStorage());
1632 columnBuilder.ValueRange(physicalColumnDesc.GetValueRange());
1633 columnBuilder.Type(physicalColumnDesc.GetType());
1634 columnBuilder.RepresentationIndex(physicalColumnDesc.GetRepresentationIndex());
1635 columnBuilder.Index(fnNextColumnIndex(columnBuilder.GetFieldId(), columnBuilder.GetRepresentationIndex()));
1636
1637 auto aliasColumnDesc = columnBuilder.MakeDescriptor();
1638 if (!aliasColumnDesc)
1639 return R__FORWARD_ERROR(aliasColumnDesc);
1640 auto resVoid = descBuilder.AddColumn(aliasColumnDesc.Unwrap());
1641 if (!resVoid)
1642 return R__FORWARD_ERROR(resVoid);
1643 }
1644 bytes = frame + frameSize;
1645
1646 std::uint32_t nExtraTypeInfos;
1647 frame = bytes;
1648 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nExtraTypeInfos)) {
1649 bytes += res.Unwrap();
1650 } else {
1651 return R__FORWARD_ERROR(res);
1652 }
1653 for (unsigned i = 0; i < nExtraTypeInfos; ++i) {
1654 RExtraTypeInfoDescriptorBuilder extraTypeInfoBuilder;
1655 if (auto res = DeserializeExtraTypeInfo(bytes, fnFrameSizeLeft(), extraTypeInfoBuilder)) {
1656 bytes += res.Unwrap();
1657 } else {
1658 return R__FORWARD_ERROR(res);
1659 }
1660
1661 auto extraTypeInfoDesc = extraTypeInfoBuilder.MoveDescriptor();
1662 // We ignore unknown extra type information
1663 if (extraTypeInfoDesc)
1664 descBuilder.AddExtraTypeInfo(extraTypeInfoDesc.Unwrap());
1665 }
1666 bytes = frame + frameSize;
1667
1668 return bytes - base;
1669}
1670
1673{
1674 RContext context;
1675
1676 auto base = reinterpret_cast<unsigned char *>(buffer);
1677 auto pos = base;
1678 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1679
1681 if (auto res = SerializeFeatureFlags(desc.GetFeatureFlags(), *where)) {
1682 pos += res.Unwrap();
1683 } else {
1684 return R__FORWARD_ERROR(res);
1685 }
1686 pos += SerializeString(desc.GetName(), *where);
1687 pos += SerializeString(desc.GetDescription(), *where);
1688 pos += SerializeString(std::string("ROOT v") + ROOT_RELEASE, *where);
1689
1690 context.MapSchema(desc, /*forHeaderExtension=*/false);
1691
1692 if (auto res = SerializeSchemaDescription(*where, desc, context)) {
1693 pos += res.Unwrap();
1694 } else {
1695 return R__FORWARD_ERROR(res);
1696 }
1697
1698 std::uint64_t size = pos - base;
1699 std::uint64_t xxhash3 = 0;
1700 if (auto res = SerializeEnvelopePostscript(base, size, xxhash3)) {
1701 size += res.Unwrap();
1702 } else {
1703 return R__FORWARD_ERROR(res);
1704 }
1705
1706 context.SetHeaderSize(size);
1707 context.SetHeaderXxHash3(xxhash3);
1708 return context;
1709}
1710
1713 std::span<ROOT::DescriptorId_t> physClusterIDs,
1714 const RContext &context)
1715{
1716 auto base = reinterpret_cast<unsigned char *>(buffer);
1717 auto pos = base;
1718 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1719
1721
1722 pos += SerializeUInt64(context.GetHeaderXxHash3(), *where);
1723
1724 // Cluster summaries
1725 const auto nClusters = physClusterIDs.size();
1726 auto clusterSummaryFrame = pos;
1727 pos += SerializeListFramePreamble(nClusters, *where);
1728 for (auto clusterId : physClusterIDs) {
1729 const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1730 RClusterSummary summary{clusterDesc.GetFirstEntryIndex(), clusterDesc.GetNEntries(), 0};
1731 if (auto res = SerializeClusterSummary(summary, *where)) {
1732 pos += res.Unwrap();
1733 } else {
1734 return R__FORWARD_ERROR(res);
1735 }
1736 }
1737 if (auto res = SerializeFramePostscript(buffer ? clusterSummaryFrame : nullptr, pos - clusterSummaryFrame)) {
1738 pos += res.Unwrap();
1739 } else {
1740 return R__FORWARD_ERROR(res);
1741 }
1742
1743 // Page locations
1744 auto topMostFrame = pos;
1745 pos += SerializeListFramePreamble(nClusters, *where);
1746
1747 for (auto clusterId : physClusterIDs) {
1748 const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1749 // Get an ordered set of physical column ids
1750 std::set<ROOT::DescriptorId_t> onDiskColumnIds;
1751 for (const auto &columnRange : clusterDesc.GetColumnRangeIterable())
1752 onDiskColumnIds.insert(context.GetOnDiskColumnId(columnRange.GetPhysicalColumnId()));
1753
1754 auto outerFrame = pos;
1755 pos += SerializeListFramePreamble(onDiskColumnIds.size(), *where);
1756 for (auto onDiskId : onDiskColumnIds) {
1757 auto memId = context.GetMemColumnId(onDiskId);
1758 const auto &columnRange = clusterDesc.GetColumnRange(memId);
1759
1760 auto innerFrame = pos;
1761 if (columnRange.IsSuppressed()) {
1762 // Empty page range
1763 pos += SerializeListFramePreamble(0, *where);
1765 } else {
1766 const auto &pageRange = clusterDesc.GetPageRange(memId);
1767 pos += SerializeListFramePreamble(pageRange.GetPageInfos().size(), *where);
1768
1769 for (const auto &pi : pageRange.GetPageInfos()) {
1770 std::int32_t nElements =
1771 pi.HasChecksum() ? -static_cast<std::int32_t>(pi.GetNElements()) : pi.GetNElements();
1772 pos += SerializeUInt32(nElements, *where);
1773 if (auto res = SerializeLocator(pi.GetLocator(), *where)) {
1774 pos += res.Unwrap();
1775 } else {
1776 return R__FORWARD_ERROR(res);
1777 }
1778 }
1779 pos += SerializeInt64(columnRange.GetFirstElementIndex(), *where);
1780 pos += SerializeUInt32(columnRange.GetCompressionSettings().value(), *where);
1781 }
1782
1783 if (auto res = SerializeFramePostscript(buffer ? innerFrame : nullptr, pos - innerFrame)) {
1784 pos += res.Unwrap();
1785 } else {
1786 return R__FORWARD_ERROR(res);
1787 }
1788 }
1789 if (auto res = SerializeFramePostscript(buffer ? outerFrame : nullptr, pos - outerFrame)) {
1790 pos += res.Unwrap();
1791 } else {
1792 return R__FORWARD_ERROR(res);
1793 }
1794 }
1795
1796 if (auto res = SerializeFramePostscript(buffer ? topMostFrame : nullptr, pos - topMostFrame)) {
1797 pos += res.Unwrap();
1798 } else {
1799 return R__FORWARD_ERROR(res);
1800 }
1801 std::uint64_t size = pos - base;
1802 if (auto res = SerializeEnvelopePostscript(base, size)) {
1803 size += res.Unwrap();
1804 } else {
1805 return R__FORWARD_ERROR(res);
1806 }
1807 return size;
1808}
1809
1811 const ROOT::RNTupleDescriptor &desc,
1812 const RContext &context)
1813{
1814 auto base = reinterpret_cast<unsigned char *>(buffer);
1815 auto pos = base;
1816 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1817
1819
1820 // NOTE: we currently serialize all feature flags in the footer, even those that were already written in the
1821 // header. This is fine, as they will be logically OR-ed together during deserialization.
1822 if (auto res = SerializeFeatureFlags(desc.GetFeatureFlags(), *where)) {
1823 pos += res.Unwrap();
1824 } else {
1825 return R__FORWARD_ERROR(res);
1826 }
1827 pos += SerializeUInt64(context.GetHeaderXxHash3(), *where);
1828
1829 // Schema extension, i.e. incremental changes with respect to the header
1830 auto frame = pos;
1831 pos += SerializeRecordFramePreamble(*where);
1832 if (auto res = SerializeSchemaDescription(*where, desc, context, /*forHeaderExtension=*/true)) {
1833 pos += res.Unwrap();
1834 } else {
1835 return R__FORWARD_ERROR(res);
1836 }
1837 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1838 pos += res.Unwrap();
1839 } else {
1840 return R__FORWARD_ERROR(res);
1841 }
1842
1843 // Cluster groups
1844 frame = pos;
1845 const auto nClusterGroups = desc.GetNClusterGroups();
1846 pos += SerializeListFramePreamble(nClusterGroups, *where);
1847 for (unsigned int i = 0; i < nClusterGroups; ++i) {
1848 const auto &cgDesc = desc.GetClusterGroupDescriptor(context.GetMemClusterGroupId(i));
1849 RClusterGroup clusterGroup;
1850 clusterGroup.fMinEntry = cgDesc.GetMinEntry();
1851 clusterGroup.fEntrySpan = cgDesc.GetEntrySpan();
1852 clusterGroup.fNClusters = cgDesc.GetNClusters();
1853 clusterGroup.fPageListEnvelopeLink.fLength = cgDesc.GetPageListLength();
1854 clusterGroup.fPageListEnvelopeLink.fLocator = cgDesc.GetPageListLocator();
1855 if (auto res = SerializeClusterGroup(clusterGroup, *where)) {
1856 pos += res.Unwrap();
1857 } else {
1858 return R__FORWARD_ERROR(res);
1859 }
1860 }
1861 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1862 pos += res.Unwrap();
1863 } else {
1864 return R__FORWARD_ERROR(res);
1865 }
1866
1867 // Attributes
1868 frame = pos;
1869 const auto nAttributeSets = desc.GetNAttributeSets();
1870 if (nAttributeSets > 0) {
1871 R__LOG_WARNING(NTupleLog()) << "RNTuple Attributes are experimental. They are not guaranteed to be readable "
1872 "back in the future (but your main data is)";
1873 }
1874 pos += SerializeListFramePreamble(nAttributeSets, *where);
1875 for (const auto &attrSet : desc.GetAttrSetIterable()) {
1876 if (auto res = SerializeAttributeSet(attrSet, *where)) {
1877 pos += res.Unwrap();
1878 } else {
1879 return R__FORWARD_ERROR(res);
1880 }
1881 }
1882 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1883 pos += res.Unwrap();
1884 } else {
1885 return R__FORWARD_ERROR(res);
1886 }
1887
1888 std::uint32_t size = pos - base;
1889 if (auto res = SerializeEnvelopePostscript(base, size)) {
1890 size += res.Unwrap();
1891 } else {
1892 return R__FORWARD_ERROR(res);
1893 }
1894 return size;
1895}
1896
1899 void *buffer)
1900{
1901 auto base = reinterpret_cast<unsigned char *>(buffer);
1902 auto pos = base;
1903 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1904
1905 auto frame = pos;
1907 pos += SerializeUInt16(attrDesc.GetSchemaVersionMajor(), *where);
1908 pos += SerializeUInt16(attrDesc.GetSchemaVersionMinor(), *where);
1909 pos += SerializeUInt32(attrDesc.GetAnchorLength(), *where);
1910 if (auto res = SerializeLocator(attrDesc.GetAnchorLocator(), *where)) {
1911 pos += res.Unwrap();
1912 } else {
1913 return R__FORWARD_ERROR(res);
1914 }
1915 pos += SerializeString(attrDesc.GetName(), *where);
1916 auto size = pos - frame;
1917 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, size)) {
1918 return size;
1919 } else {
1920 return R__FORWARD_ERROR(res);
1921 }
1922}
1923
1924static ROOT::RResult<void> CheckFeatureFlags(const std::vector<std::uint64_t> &featureFlags)
1925{
1926 for (std::size_t i = 0; i < featureFlags.size(); ++i) {
1927 if (!featureFlags[i])
1928 continue;
1929 // NOTE: this assumes all valid feature flags are consecutive, thus we can just check the highest one set.
1930 unsigned int highestBitSet = 64 * i + (63 - ROOT::Internal::LeadingZeroes(featureFlags[i]));
1932 return R__FAIL("unsupported format feature: " + std::to_string(highestBitSet));
1933 }
1935}
1936
1938 RNTupleDescriptorBuilder &descBuilder)
1939{
1940 auto base = reinterpret_cast<const unsigned char *>(buffer);
1941 auto bytes = base;
1942 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1943
1944 std::uint64_t xxhash3{0};
1945 if (auto res = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypeHeader, xxhash3)) {
1946 bytes += res.Unwrap();
1947 } else {
1948 return R__FORWARD_ERROR(res);
1949 }
1950 descBuilder.SetOnDiskHeaderXxHash3(xxhash3);
1951
1952 std::vector<std::uint64_t> featureFlags;
1953 if (auto res = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags)) {
1954 bytes += res.Unwrap();
1955 } else {
1956 return R__FORWARD_ERROR(res);
1957 }
1958 if (auto res = CheckFeatureFlags(featureFlags); !res) {
1959 return R__FORWARD_ERROR(res);
1960 }
1961
1962 std::string name;
1963 std::string description;
1964 std::string writer;
1965 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), name)) {
1966 bytes += res.Unwrap();
1967 } else {
1968 return R__FORWARD_ERROR(res);
1969 }
1970 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), description)) {
1971 bytes += res.Unwrap();
1972 } else {
1973 return R__FORWARD_ERROR(res);
1974 }
1975 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), writer)) {
1976 bytes += res.Unwrap();
1977 } else {
1978 return R__FORWARD_ERROR(res);
1979 }
1980 descBuilder.SetNTuple(name, description);
1981
1982 // Zero field
1983 descBuilder.AddField(RFieldDescriptorBuilder()
1984 .FieldId(kZeroFieldId)
1986 .MakeDescriptor()
1987 .Unwrap());
1988 if (auto res = DeserializeSchemaDescription(bytes, fnBufSizeLeft(), descBuilder)) {
1989 return RResult<void>::Success();
1990 } else {
1991 return R__FORWARD_ERROR(res);
1992 }
1993}
1994
1996 RNTupleDescriptorBuilder &descBuilder)
1997{
1998 auto base = reinterpret_cast<const unsigned char *>(buffer);
1999 auto bytes = base;
2000 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
2001 if (auto res = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypeFooter)) {
2002 bytes += res.Unwrap();
2003 } else {
2004 return R__FORWARD_ERROR(res);
2005 }
2006
2007 std::vector<std::uint64_t> featureFlags;
2008 if (auto res = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags)) {
2009 bytes += res.Unwrap();
2010 } else {
2011 return R__FORWARD_ERROR(res);
2012 }
2013 if (auto res = CheckFeatureFlags(featureFlags); !res) {
2014 return R__FORWARD_ERROR(res);
2015 }
2016
2017 std::uint64_t xxhash3{0};
2018 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
2019 return R__FAIL("footer too short");
2020 bytes += DeserializeUInt64(bytes, xxhash3);
2021 if (xxhash3 != descBuilder.GetDescriptor().GetOnDiskHeaderXxHash3())
2022 return R__FAIL("XxHash-3 mismatch between header and footer");
2023
2024 std::uint64_t frameSize;
2025 auto frame = bytes;
2026 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
2027
2028 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize)) {
2029 bytes += res.Unwrap();
2030 } else {
2031 return R__FORWARD_ERROR(res);
2032 }
2033 if (fnFrameSizeLeft() > 0) {
2034 descBuilder.BeginHeaderExtension();
2035 if (auto res = DeserializeSchemaDescription(bytes, fnFrameSizeLeft(), descBuilder); !res) {
2036 return R__FORWARD_ERROR(res);
2037 }
2038 }
2039 bytes = frame + frameSize;
2040
2041 {
2042 std::uint32_t nClusterGroups;
2043 frame = bytes;
2044 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nClusterGroups)) {
2045 bytes += res.Unwrap();
2046 } else {
2047 return R__FORWARD_ERROR(res);
2048 }
2049 for (std::uint32_t groupId = 0; groupId < nClusterGroups; ++groupId) {
2050 RClusterGroup clusterGroup;
2051 if (auto res = DeserializeClusterGroup(bytes, fnFrameSizeLeft(), clusterGroup)) {
2052 bytes += res.Unwrap();
2053 } else {
2054 return R__FORWARD_ERROR(res);
2055 }
2056
2058 RClusterGroupDescriptorBuilder clusterGroupBuilder;
2059 clusterGroupBuilder.ClusterGroupId(groupId)
2062 .MinEntry(clusterGroup.fMinEntry)
2063 .EntrySpan(clusterGroup.fEntrySpan)
2064 .NClusters(clusterGroup.fNClusters);
2065 descBuilder.AddClusterGroup(clusterGroupBuilder.MoveDescriptor().Unwrap());
2066 }
2067 bytes = frame + frameSize;
2068 }
2069
2070 // NOTE: Attributes were introduced in v1.0.1.0, so this section may be missing.
2071 // Testing for > 8 because bufSize includes the checksum.
2072 if (fnBufSizeLeft() > 8) {
2073 std::uint32_t nAttributeSets;
2074 frame = bytes;
2075 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nAttributeSets)) {
2076 bytes += res.Unwrap();
2077 } else {
2078 return R__FORWARD_ERROR(res);
2079 }
2080 if (nAttributeSets > 0) {
2081 R__LOG_WARNING(NTupleLog()) << "RNTuple Attributes are experimental. They are not guaranteed to be readable "
2082 "back in the future (but your main data is)";
2083 }
2084 for (std::uint32_t attrSetId = 0; attrSetId < nAttributeSets; ++attrSetId) {
2086 if (auto res = DeserializeAttributeSet(bytes, fnBufSizeLeft(), attrSetDescBld)) {
2087 descBuilder.AddAttributeSet(attrSetDescBld.MoveDescriptor().Unwrap());
2088 bytes += res.Unwrap();
2089 } else {
2090 return R__FORWARD_ERROR(res);
2091 }
2092 }
2093 bytes = frame + frameSize;
2094 }
2095
2096 return RResult<void>::Success();
2097}
2098
2100 const void *buffer, std::uint64_t bufSize, Experimental::Internal::RNTupleAttrSetDescriptorBuilder &attrSetDescBld)
2101{
2102 auto base = reinterpret_cast<const unsigned char *>(buffer);
2103 auto bytes = base;
2104 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
2105
2106 std::uint64_t frameSize;
2107 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize)) {
2108 bytes += res.Unwrap();
2109 } else {
2110 return R__FORWARD_ERROR(res);
2111 }
2112 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
2113 return R__FAIL("record frame too short");
2114 std::uint16_t vMajor, vMinor;
2115 bytes += DeserializeUInt16(bytes, vMajor);
2116 bytes += DeserializeUInt16(bytes, vMinor);
2117 std::uint32_t anchorLen;
2118 bytes += DeserializeUInt32(bytes, anchorLen);
2119 RNTupleLocator anchorLoc;
2120 if (auto res = DeserializeLocator(bytes, fnBufSizeLeft(), anchorLoc)) {
2121 bytes += res.Unwrap();
2122 } else {
2123 return R__FORWARD_ERROR(res);
2124 }
2125 std::string name;
2126 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), name)) {
2127 bytes += res.Unwrap();
2128 } else {
2129 return R__FORWARD_ERROR(res);
2130 }
2131
2132 attrSetDescBld.SchemaVersion(vMajor, vMinor).AnchorLength(anchorLen).AnchorLocator(anchorLoc).Name(name);
2133
2134 return frameSize;
2135}
2136
2138ROOT::Internal::RNTupleSerializer::DeserializePageListRaw(const void *buffer, std::uint64_t bufSize,
2139 ROOT::DescriptorId_t clusterGroupId,
2140 const ROOT::RNTupleDescriptor &desc)
2141{
2142 auto base = reinterpret_cast<const unsigned char *>(buffer);
2143 auto bytes = base;
2144 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
2145
2146 if (auto res = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypePageList)) {
2147 bytes += res.Unwrap();
2148 } else {
2149 return R__FORWARD_ERROR(res);
2150 }
2151
2152 std::uint64_t xxhash3{0};
2153 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
2154 return R__FAIL("page list too short");
2155 bytes += DeserializeUInt64(bytes, xxhash3);
2156 if (xxhash3 != desc.GetOnDiskHeaderXxHash3())
2157 return R__FAIL("XxHash-3 mismatch between header and page list");
2158
2159 std::vector<RClusterDescriptorBuilder> clusterBuilders;
2160 ROOT::DescriptorId_t firstClusterId{0};
2161 for (ROOT::DescriptorId_t i = 0; i < clusterGroupId; ++i) {
2162 firstClusterId = firstClusterId + desc.GetClusterGroupDescriptor(i).GetNClusters();
2163 }
2164
2165 std::uint64_t clusterSummaryFrameSize;
2166 auto clusterSummaryFrame = bytes;
2167 auto fnClusterSummaryFrameSizeLeft = [&]() { return clusterSummaryFrameSize - (bytes - clusterSummaryFrame); };
2168
2169 std::uint32_t nClusterSummaries;
2170 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), clusterSummaryFrameSize, nClusterSummaries)) {
2171 bytes += res.Unwrap();
2172 } else {
2173 return R__FORWARD_ERROR(res);
2174 }
2175 for (auto clusterId = firstClusterId; clusterId < firstClusterId + nClusterSummaries; ++clusterId) {
2176 RClusterSummary clusterSummary;
2177 if (auto res = DeserializeClusterSummary(bytes, fnClusterSummaryFrameSizeLeft(), clusterSummary)) {
2178 bytes += res.Unwrap();
2179 } else {
2180 return R__FORWARD_ERROR(res);
2181 }
2182
2184 builder.ClusterId(clusterId).FirstEntryIndex(clusterSummary.fFirstEntry).NEntries(clusterSummary.fNEntries);
2185 clusterBuilders.emplace_back(std::move(builder));
2186 }
2187 bytes = clusterSummaryFrame + clusterSummaryFrameSize;
2188
2189 std::uint64_t topMostFrameSize;
2190 auto topMostFrame = bytes;
2191 auto fnTopMostFrameSizeLeft = [&]() { return topMostFrameSize - (bytes - topMostFrame); };
2192
2193 std::uint32_t nClusters;
2194 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), topMostFrameSize, nClusters)) {
2195 bytes += res.Unwrap();
2196 } else {
2197 return R__FORWARD_ERROR(res);
2198 }
2199
2200 if (nClusters != nClusterSummaries)
2201 return R__FAIL("mismatch between number of clusters and number of cluster summaries");
2202
2203 for (std::uint32_t i = 0; i < nClusters; ++i) {
2204 std::uint64_t outerFrameSize;
2205 auto outerFrame = bytes;
2206 auto fnOuterFrameSizeLeft = [&]() { return outerFrameSize - (bytes - outerFrame); };
2207
2208 std::uint32_t nColumns;
2209 if (auto res = DeserializeFrameHeader(bytes, fnTopMostFrameSizeLeft(), outerFrameSize, nColumns)) {
2210 bytes += res.Unwrap();
2211 } else {
2212 return R__FORWARD_ERROR(res);
2213 }
2214
2215 for (std::uint32_t j = 0; j < nColumns; ++j) {
2216 std::uint64_t innerFrameSize;
2217 auto innerFrame = bytes;
2218 auto fnInnerFrameSizeLeft = [&]() { return innerFrameSize - (bytes - innerFrame); };
2219
2220 std::uint32_t nPages;
2221 if (auto res = DeserializeFrameHeader(bytes, fnOuterFrameSizeLeft(), innerFrameSize, nPages)) {
2222 bytes += res.Unwrap();
2223 } else {
2224 return R__FORWARD_ERROR(res);
2225 }
2226
2228 pageRange.SetPhysicalColumnId(j);
2229 for (std::uint32_t k = 0; k < nPages; ++k) {
2230 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
2231 return R__FAIL("inner frame too short");
2232 std::int32_t nElements;
2233 bool hasChecksum = false;
2234 RNTupleLocator locator;
2235 bytes += DeserializeInt32(bytes, nElements);
2236 if (nElements < 0) {
2237 nElements = -nElements;
2238 hasChecksum = true;
2239 }
2240 if (auto res = DeserializeLocator(bytes, fnInnerFrameSizeLeft(), locator)) {
2241 bytes += res.Unwrap();
2242 } else {
2243 return R__FORWARD_ERROR(res);
2244 }
2245 pageRange.GetPageInfos().push_back({static_cast<std::uint32_t>(nElements), locator, hasChecksum});
2246 }
2247
2248 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::int64_t)))
2249 return R__FAIL("page list frame too short");
2250 std::int64_t columnOffset;
2251 bytes += DeserializeInt64(bytes, columnOffset);
2252 if (columnOffset < 0) {
2253 if (nPages > 0)
2254 return R__FAIL("unexpected non-empty page list");
2255 clusterBuilders[i].MarkSuppressedColumnRange(j);
2256 } else {
2257 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
2258 return R__FAIL("page list frame too short");
2259 std::uint32_t compressionSettings;
2260 bytes += DeserializeUInt32(bytes, compressionSettings);
2261 clusterBuilders[i].CommitColumnRange(j, columnOffset, compressionSettings, pageRange);
2262 }
2263
2264 bytes = innerFrame + innerFrameSize;
2265 } // loop over columns
2266
2267 bytes = outerFrame + outerFrameSize;
2268 } // loop over clusters
2269
2270 return clusterBuilders;
2271}
2272
2274 ROOT::DescriptorId_t clusterGroupId,
2277{
2278 auto clusterBuildersRes = RNTupleSerializer::DeserializePageListRaw(buffer, bufSize, clusterGroupId, desc);
2279 if (!clusterBuildersRes)
2280 return R__FORWARD_ERROR(clusterBuildersRes);
2281
2282 auto clusterBuilders = clusterBuildersRes.Unwrap();
2283
2284 std::vector<ROOT::RClusterDescriptor> clusters;
2285 clusters.reserve(clusterBuilders.size());
2286
2287 // Conditionally fixup the clusters depending on the attach purpose
2288 switch (mode) {
2290 for (auto &builder : clusterBuilders) {
2291 if (auto res = builder.CommitSuppressedColumnRanges(desc); !res)
2292 return R__FORWARD_RESULT(res);
2293 builder.AddExtendedColumnRanges(desc);
2294 clusters.emplace_back(builder.MoveDescriptor().Unwrap());
2295 }
2296 break;
2298 for (auto &builder : clusterBuilders) {
2299 if (auto res = builder.CommitSuppressedColumnRanges(desc); !res)
2300 return R__FORWARD_RESULT(res);
2301 clusters.emplace_back(builder.MoveDescriptor().Unwrap());
2302 }
2303 break;
2305 for (auto &builder : clusterBuilders)
2306 clusters.emplace_back(builder.MoveDescriptor().Unwrap());
2307 break;
2308 }
2309
2310 desc.AddClusterGroupDetails(clusterGroupId, clusters);
2311
2312 return RResult<void>::Success();
2313}
2314
2316{
2317 TList streamerInfos;
2318 for (auto si : infos) {
2319 assert(si.first == si.second->GetNumber());
2320 streamerInfos.Add(si.second);
2321 }
2323 buffer.WriteObject(&streamerInfos);
2324 assert(buffer.Length() > 0);
2325 return std::string{buffer.Buffer(), static_cast<UInt_t>(buffer.Length())};
2326}
2327
2330{
2331 StreamerInfoMap_t infoMap;
2332
2333 TBufferFile buffer(TBuffer::kRead, extraTypeInfoContent.length(), const_cast<char *>(extraTypeInfoContent.data()),
2334 false /* adopt */);
2335 auto infoList = reinterpret_cast<TList *>(buffer.ReadObject(TList::Class()));
2336
2337 TObjLink *lnk = infoList->FirstLink();
2338 while (lnk) {
2339 auto info = reinterpret_cast<TStreamerInfo *>(lnk->GetObject());
2340 info->BuildCheck();
2341 infoMap[info->GetNumber()] = info->GetClass()->GetStreamerInfo(info->GetClassVersion());
2342 assert(info->GetNumber() == infoMap[info->GetNumber()]->GetNumber());
2343 lnk = lnk->Next();
2344 }
2345
2346 delete infoList;
2347
2348 return infoMap;
2349}
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
Definition RError.hxx:303
#define R__FORWARD_RESULT(res)
Short-hand to return an RResult<T> value from a subroutine to the calling stack frame.
Definition RError.hxx:301
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:299
#define R__LOG_WARNING(...)
Definition RLogger.hxx:357
#define R__LOG_DEBUG(DEBUGLEVEL,...)
Definition RLogger.hxx:359
static ROOT::RResult< void > CheckFeatureFlags(const std::vector< std::uint64_t > &featureFlags)
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define ROOT_RELEASE
Definition RVersion.hxx:44
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t nitems
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t bytes
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:148
A helper class for serializing and deserialization of the RNTuple binary format.
static constexpr std::uint16_t kFlagDeferredColumn
static RResult< std::uint32_t > DeserializeString(const void *buffer, std::uint64_t bufSize, std::string &val)
static constexpr std::uint16_t kFlagIsSoACollection
static std::uint32_t SerializeUInt32(std::uint32_t val, void *buffer)
static RResult< std::uint32_t > SerializeFieldStructure(ROOT::ENTupleStructure structure, void *buffer)
While we could just interpret the enums as ints, we make the translation explicit in order to avoid a...
static std::uint32_t DeserializeUInt32(const void *buffer, std::uint32_t &val)
static RResult< std::uint32_t > DeserializeFrameHeader(const void *buffer, std::uint64_t bufSize, std::uint64_t &frameSize, std::uint32_t &nitems)
static constexpr std::uint16_t kFlagRepetitiveField
static RResult< std::uint32_t > SerializeColumnType(ROOT::ENTupleColumnType type, void *buffer)
static RResult< std::uint32_t > SerializeFramePostscript(void *frame, std::uint64_t size)
static std::uint32_t SerializeUInt16(std::uint16_t val, void *buffer)
static constexpr std::uint16_t kFlagProjectedField
static std::uint32_t DeserializeInt64(const void *buffer, std::int64_t &val)
static std::uint32_t SerializeString(const std::string &val, void *buffer)
static RResult< std::uint32_t > SerializeExtraTypeInfoId(ROOT::EExtraTypeInfoIds id, void *buffer)
static std::uint32_t DeserializeUInt16(const void *buffer, std::uint16_t &val)
static constexpr std::uint16_t kFlagHasValueRange
static RResult< std::uint32_t > DeserializeColumnType(const void *buffer, ROOT::ENTupleColumnType &type)
static constexpr std::uint16_t kFlagHasTypeChecksum
static RResult< std::uint32_t > DeserializeExtraTypeInfoId(const void *buffer, ROOT::EExtraTypeInfoIds &id)
static std::uint32_t SerializeRecordFramePreamble(void *buffer)
static RResult< std::uint32_t > DeserializeFieldStructure(const void *buffer, ROOT::ENTupleStructure &structure)
static std::uint32_t SerializeInt64(std::int64_t val, void *buffer)
static std::uint32_t DeserializeUInt64(const void *buffer, std::uint64_t &val)
static std::uint32_t SerializeUInt64(std::uint64_t val, void *buffer)
The available trivial, native content types of a column.
RNTupleAttrSetDescriptorBuilder & AnchorLocator(const RNTupleLocator &loc)
RNTupleAttrSetDescriptorBuilder & SchemaVersion(std::uint16_t major, std::uint16_t minor)
RResult< ROOT::Experimental::RNTupleAttrSetDescriptor > MoveDescriptor()
Attempt to make an AttributeSet descriptor.
RNTupleAttrSetDescriptorBuilder & Name(std::string_view name)
RNTupleAttrSetDescriptorBuilder & AnchorLength(std::uint32_t length)
Metadata stored for every Attribute Set linked to an RNTuple.
const RNTupleLocator & GetAnchorLocator() const
A helper class for piece-wise construction of an RClusterDescriptor.
RClusterDescriptorBuilder & NEntries(std::uint64_t nEntries)
RClusterDescriptorBuilder & ClusterId(ROOT::DescriptorId_t clusterId)
RClusterDescriptorBuilder & FirstEntryIndex(std::uint64_t firstEntryIndex)
A helper class for piece-wise construction of an RClusterGroupDescriptor.
RClusterGroupDescriptorBuilder & EntrySpan(std::uint64_t entrySpan)
RClusterGroupDescriptorBuilder & PageListLocator(const RNTupleLocator &pageListLocator)
RClusterGroupDescriptorBuilder & PageListLength(std::uint64_t pageListLength)
RClusterGroupDescriptorBuilder & MinEntry(std::uint64_t minEntry)
RResult< RClusterGroupDescriptor > MoveDescriptor()
RClusterGroupDescriptorBuilder & ClusterGroupId(ROOT::DescriptorId_t clusterGroupId)
RClusterGroupDescriptorBuilder & NClusters(std::uint32_t nClusters)
A helper class for piece-wise construction of an RColumnDescriptor.
ROOT::DescriptorId_t GetRepresentationIndex() const
RColumnDescriptorBuilder & SetSuppressedDeferred()
RColumnDescriptorBuilder & LogicalColumnId(ROOT::DescriptorId_t logicalColumnId)
RResult< RColumnDescriptor > MakeDescriptor() const
Attempt to make a column descriptor.
RColumnDescriptorBuilder & FieldId(ROOT::DescriptorId_t fieldId)
RColumnDescriptorBuilder & BitsOnStorage(std::uint16_t bitsOnStorage)
RColumnDescriptorBuilder & ValueRange(double min, double max)
RColumnDescriptorBuilder & Type(ROOT::ENTupleColumnType type)
RColumnDescriptorBuilder & PhysicalColumnId(ROOT::DescriptorId_t physicalColumnId)
RColumnDescriptorBuilder & FirstElementIndex(std::uint64_t firstElementIdx)
RColumnDescriptorBuilder & Index(std::uint32_t index)
RColumnDescriptorBuilder & RepresentationIndex(std::uint16_t representationIndex)
A helper class for piece-wise construction of an RExtraTypeInfoDescriptor.
RResult< RExtraTypeInfoDescriptor > MoveDescriptor()
RExtraTypeInfoDescriptorBuilder & ContentId(EExtraTypeInfoIds contentId)
RExtraTypeInfoDescriptorBuilder & TypeName(const std::string &typeName)
RExtraTypeInfoDescriptorBuilder & Content(const std::string &content)
RExtraTypeInfoDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
A helper class for piece-wise construction of an RFieldDescriptor.
RFieldDescriptorBuilder & NRepetitions(std::uint64_t nRepetitions)
RFieldDescriptorBuilder & Structure(const ROOT::ENTupleStructure &structure)
RFieldDescriptorBuilder & TypeAlias(const std::string &typeAlias)
RFieldDescriptorBuilder & ProjectionSourceId(ROOT::DescriptorId_t id)
RFieldDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
RFieldDescriptorBuilder & IsSoACollection(bool val)
RFieldDescriptorBuilder & TypeChecksum(const std::optional< std::uint32_t > typeChecksum)
RResult< RFieldDescriptor > MakeDescriptor() const
Attempt to make a field descriptor.
RFieldDescriptorBuilder & ParentId(ROOT::DescriptorId_t id)
RFieldDescriptorBuilder & FieldDescription(const std::string &fieldDescription)
RFieldDescriptorBuilder & FieldVersion(std::uint32_t fieldVersion)
RFieldDescriptorBuilder & FieldName(const std::string &fieldName)
RFieldDescriptorBuilder & FieldId(ROOT::DescriptorId_t fieldId)
RFieldDescriptorBuilder & TypeName(const std::string &typeName)
A helper class for piece-wise construction of an RNTupleDescriptor.
void SetNTuple(const std::string_view name, const std::string_view description)
RResult< void > AddColumn(RColumnDescriptor &&columnDesc)
RResult< void > AddAttributeSet(Experimental::RNTupleAttrSetDescriptor &&attrSetDesc)
RResult< void > AddFieldProjection(ROOT::DescriptorId_t sourceId, ROOT::DescriptorId_t targetId)
RResult< void > AddExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc)
void ShiftAliasColumns(std::uint32_t offset)
Shift column IDs of alias columns by offset
const RNTupleDescriptor & GetDescriptor() const
void BeginHeaderExtension()
Mark the beginning of the header extension; any fields and columns added after a call to this functio...
RResult< void > AddFieldLink(ROOT::DescriptorId_t fieldId, ROOT::DescriptorId_t linkId)
void AddField(const RFieldDescriptor &fieldDesc)
RResult< void > AddClusterGroup(RClusterGroupDescriptor &&clusterGroup)
void SetOnDiskHeaderXxHash3(std::uint64_t xxhash3)
void AddToOnDiskFooterSize(std::uint64_t size)
The real footer size also include the page list envelopes.
The serialization context is used for the piecewise serialization of a descriptor.
ROOT::DescriptorId_t GetOnDiskFieldId(ROOT::DescriptorId_t memId) const
ROOT::DescriptorId_t GetMemColumnId(ROOT::DescriptorId_t onDiskId) const
ROOT::DescriptorId_t GetMemClusterGroupId(ROOT::DescriptorId_t onDiskId) const
ROOT::DescriptorId_t GetOnDiskColumnId(ROOT::DescriptorId_t memId) const
void MapSchema(const RNTupleDescriptor &desc, bool forHeaderExtension)
Map in-memory field and column IDs to their on-disk counterparts.
ROOT::DescriptorId_t MapPhysicalColumnId(ROOT::DescriptorId_t memId)
Map an in-memory column ID to its on-disk counterpart.
ROOT::DescriptorId_t GetMemClusterId(ROOT::DescriptorId_t onDiskId) const
const std::vector< ROOT::DescriptorId_t > & GetOnDiskFieldList() const
Return a vector containing the in-memory field ID for each on-disk counterpart, in order,...
ROOT::DescriptorId_t MapFieldId(ROOT::DescriptorId_t memId)
Map an in-memory field ID to its on-disk counterpart.
A helper class for serializing and deserialization of the RNTuple binary format.
static std::uint32_t SerializeXxHash3(const unsigned char *data, std::uint64_t length, std::uint64_t &xxhash3, void *buffer)
Writes a XxHash-3 64bit checksum of the byte range given by data and length.
static RResult< std::vector< ROOT::Internal::RClusterDescriptorBuilder > > DeserializePageListRaw(const void *buffer, std::uint64_t bufSize, ROOT::DescriptorId_t clusterGroupId, const RNTupleDescriptor &desc)
static RResult< std::uint32_t > SerializeSchemaDescription(void *buffer, const RNTupleDescriptor &desc, const RContext &context, bool forHeaderExtension=false)
Serialize the schema description in desc into buffer.
static RResult< std::uint32_t > DeserializeString(const void *buffer, std::uint64_t bufSize, std::string &val)
static constexpr std::uint16_t kEnvelopeTypePageList
static RResult< std::uint32_t > SerializeEnvelopeLink(const REnvelopeLink &envelopeLink, void *buffer)
static std::uint32_t SerializeInt32(std::int32_t val, void *buffer)
static RResult< std::uint32_t > DeserializeEnvelopeLink(const void *buffer, std::uint64_t bufSize, REnvelopeLink &envelopeLink)
static std::uint32_t SerializeUInt32(std::uint32_t val, void *buffer)
static RResult< std::uint32_t > SerializeAttributeSet(const Experimental::RNTupleAttrSetDescriptor &attrSetDesc, void *buffer)
static RResult< std::uint32_t > SerializeFieldStructure(ROOT::ENTupleStructure structure, void *buffer)
While we could just interpret the enums as ints, we make the translation explicit in order to avoid a...
static RResult< std::uint32_t > SerializeEnvelopePostscript(unsigned char *envelope, std::uint64_t size)
static RResult< std::uint32_t > SerializeFeatureFlags(const std::vector< std::uint64_t > &flags, void *buffer)
static std::uint32_t DeserializeUInt32(const void *buffer, std::uint32_t &val)
static RResult< std::uint32_t > DeserializeFrameHeader(const void *buffer, std::uint64_t bufSize, std::uint64_t &frameSize, std::uint32_t &nitems)
static RResult< std::uint32_t > DeserializeAttributeSet(const void *buffer, std::uint64_t bufSize, Experimental::Internal::RNTupleAttrSetDescriptorBuilder &attrSetDescBld)
static RResult< std::uint32_t > DeserializeEnvelope(const void *buffer, std::uint64_t bufSize, std::uint16_t expectedType)
static constexpr int64_t kSuppressedColumnMarker
static RResult< std::uint32_t > SerializeColumnType(ROOT::ENTupleColumnType type, void *buffer)
static std::uint32_t SerializeListFramePreamble(std::uint32_t nitems, void *buffer)
static std::uint32_t SerializeInt16(std::int16_t val, void *buffer)
static RResult< std::uint32_t > SerializeFramePostscript(void *frame, std::uint64_t size)
static constexpr std::uint16_t kEnvelopeTypeFooter
static RResult< std::uint32_t > DeserializeClusterGroup(const void *buffer, std::uint64_t bufSize, RClusterGroup &clusterGroup)
static RResult< std::uint32_t > DeserializeLocator(const void *buffer, std::uint64_t bufSize, RNTupleLocator &locator)
static std::uint32_t SerializeUInt16(std::uint16_t val, void *buffer)
static RResult< void > DeserializePageList(const void *buffer, std::uint64_t bufSize, ROOT::DescriptorId_t clusterGroupId, RNTupleDescriptor &desc, EDescriptorDeserializeMode mode)
static RResult< void > DeserializeFooter(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RNTupleDescriptorBuilder &descBuilder)
static std::uint32_t DeserializeInt64(const void *buffer, std::int64_t &val)
static std::uint32_t SerializeEnvelopePreamble(std::uint16_t envelopeType, void *buffer)
static std::uint32_t DeserializeInt32(const void *buffer, std::int32_t &val)
static std::uint32_t SerializeString(const std::string &val, void *buffer)
std::map< Int_t, TVirtualStreamerInfo * > StreamerInfoMap_t
static RResult< std::uint32_t > SerializeExtraTypeInfoId(ROOT::EExtraTypeInfoIds id, void *buffer)
static RResult< StreamerInfoMap_t > DeserializeStreamerInfos(const std::string &extraTypeInfoContent)
static std::uint32_t DeserializeUInt16(const void *buffer, std::uint16_t &val)
static RResult< void > VerifyXxHash3(const unsigned char *data, std::uint64_t length, std::uint64_t &xxhash3)
Expects an xxhash3 checksum in the 8 bytes following data + length and verifies it.
static RResult< std::uint32_t > SerializeClusterSummary(const RClusterSummary &clusterSummary, void *buffer)
static RResult< std::uint32_t > DeserializeColumnType(const void *buffer, ROOT::ENTupleColumnType &type)
static constexpr ROOT::DescriptorId_t kZeroFieldId
static std::uint32_t DeserializeInt16(const void *buffer, std::int16_t &val)
static RResult< std::uint32_t > DeserializeExtraTypeInfoId(const void *buffer, ROOT::EExtraTypeInfoIds &id)
static RResult< std::uint32_t > DeserializeClusterSummary(const void *buffer, std::uint64_t bufSize, RClusterSummary &clusterSummary)
@ kForReading
Deserializes the descriptor and performs fixup on the suppressed column ranges and on clusters,...
@ kRaw
Deserializes the descriptor as-is without performing any additional fixup.
@ kForWriting
Deserializes the descriptor and performs fixup on the suppressed column ranges.
static constexpr std::uint16_t kEnvelopeTypeHeader
static RResult< std::uint32_t > SerializeClusterGroup(const RClusterGroup &clusterGroup, void *buffer)
static std::uint32_t SerializeRecordFramePreamble(void *buffer)
static RResult< std::uint32_t > SerializePageList(void *buffer, const RNTupleDescriptor &desc, std::span< ROOT::DescriptorId_t > physClusterIDs, const RContext &context)
static RResult< std::uint32_t > DeserializeFieldStructure(const void *buffer, ROOT::ENTupleStructure &structure)
static std::uint32_t SerializeInt64(std::int64_t val, void *buffer)
static RResult< void > DeserializeHeader(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RNTupleDescriptorBuilder &descBuilder)
static RResult< std::uint32_t > SerializeFooter(void *buffer, const RNTupleDescriptor &desc, const RContext &context)
static std::uint32_t DeserializeUInt64(const void *buffer, std::uint64_t &val)
static RResult< std::uint32_t > SerializeLocator(const RNTupleLocator &locator, void *buffer)
static RResult< std::uint32_t > DeserializeSchemaDescription(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RNTupleDescriptorBuilder &descBuilder)
static std::uint32_t SerializeUInt64(std::uint64_t val, void *buffer)
static RResult< std::uint32_t > DeserializeFeatureFlags(const void *buffer, std::uint64_t bufSize, std::vector< std::uint64_t > &flags)
static RResult< RContext > SerializeHeader(void *buffer, const RNTupleDescriptor &desc)
static std::string SerializeStreamerInfos(const StreamerInfoMap_t &infos)
Records the partition of data into pages for a particular column in a particular cluster.
const std::vector< RPageInfo > & GetPageInfos() const
void SetPhysicalColumnId(ROOT::DescriptorId_t id)
Metadata stored for every column of an RNTuple.
std::optional< RValueRange > GetValueRange() const
std::uint64_t GetFirstElementIndex() const
ROOT::DescriptorId_t GetFieldId() const
ROOT::ENTupleColumnType GetType() const
ROOT::DescriptorId_t GetPhysicalId() const
std::uint16_t GetRepresentationIndex() const
std::uint16_t GetBitsOnStorage() const
Field specific extra type information from the header / extenstion header.
const std::string & GetContent() const
const std::string & GetTypeName() const
EExtraTypeInfoIds GetContentId() const
Metadata stored for every field of an RNTuple.
const std::string & GetTypeAlias() const
std::uint32_t GetFieldVersion() const
const std::vector< ROOT::DescriptorId_t > & GetLogicalColumnIds() const
ROOT::ENTupleStructure GetStructure() const
std::uint64_t GetNRepetitions() const
const std::string & GetFieldDescription() const
std::optional< std::uint32_t > GetTypeChecksum() const
std::uint32_t GetTypeVersion() const
const std::string & GetFieldName() const
const std::string & GetTypeName() const
const std::vector< ROOT::DescriptorId_t > & GetExtendedColumnRepresentations() const
The on-storage metadata of an RNTuple.
const RClusterGroupDescriptor & GetClusterGroupDescriptor(ROOT::DescriptorId_t clusterGroupId) const
const RColumnDescriptor & GetColumnDescriptor(ROOT::DescriptorId_t columnId) const
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
const RFieldDescriptor & GetFieldDescriptor(ROOT::DescriptorId_t fieldId) const
std::size_t GetNExtraTypeInfos() const
RColumnDescriptorIterable GetColumnIterable() const
const std::string & GetName() const
std::vector< std::uint64_t > GetFeatureFlags() const
ROOT::DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level RNTuple data fields.
std::size_t GetNAttributeSets() const
RExtraTypeInfoDescriptorIterable GetExtraTypeInfoIterable() const
std::size_t GetNPhysicalColumns() const
const RHeaderExtension * GetHeaderExtension() const
Return header extension information; if the descriptor does not have a header extension,...
const RClusterDescriptor & GetClusterDescriptor(ROOT::DescriptorId_t clusterId) const
std::uint64_t GetOnDiskHeaderXxHash3() const
std::size_t GetNFields() const
RResult< void > AddClusterGroupDetails(ROOT::DescriptorId_t clusterGroupId, std::vector< RClusterDescriptor > &clusterDescs)
Methods to load and drop cluster group details (cluster IDs and page locations)
ROOT::Experimental::RNTupleAttrSetDescriptorIterable GetAttrSetIterable() const
std::size_t GetNLogicalColumns() const
std::size_t GetNClusterGroups() const
const std::string & GetDescription() const
RNTupleLocator payload for the kTypeMulti locator (type 0x03).
RNTupleLocator payload that is common for object stores using 64bit location information.
Generic information about the physical location of data.
std::uint64_t GetNBytesOnStorage() const
ELocatorType GetType() const
For non-disk locators, the value for the Type field.
std::uint8_t GetReserved() const
We currently only support one of the 8 available reserved bits (none are used so far).
T GetPosition() const
Note that for GetPosition() / SetPosition(), the locator type must correspond (kTypeFile,...
void SetType(ELocatorType type)
void SetPosition(std::uint64_t position)
void SetReserved(std::uint8_t reserved)
See GetReserved(): we ignore the reserved flag since we don't use it anywhere currently.
void SetNBytesOnStorage(std::uint64_t nBytesOnStorage)
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition RError.hxx:197
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
TObject * ReadObject(const TClass *cl) override
Read object from I/O buffer.
void WriteObject(const TObject *obj, Bool_t cacheReuse=kTRUE) override
Write object to I/O buffer.
@ kWrite
Definition TBuffer.h:73
@ kRead
Definition TBuffer.h:73
Int_t Length() const
Definition TBuffer.h:100
char * Buffer() const
Definition TBuffer.h:96
A doubly linked list.
Definition TList.h:38
static TClass * Class()
void Add(TObject *obj) override
Definition TList.h:81
Describes a persistent version of a class.
void BuildCheck(TFile *file=nullptr, Bool_t load=kTRUE) override
Check if built and consistent with the class dictionary.
constexpr ROOT::ENTupleStructure kTestFutureFieldStructure
std::size_t LeadingZeroes(T x)
Given an integer x, returns the number of leading 0-bits starting at the most significant bit positio...
Definition BitUtils.hxx:64
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
constexpr ENTupleColumnType kTestFutureColumnType
constexpr RNTupleLocator::ELocatorType kTestLocatorType
EExtraTypeInfoIds
Used in RExtraTypeInfoDescriptor.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr DescriptorId_t kInvalidDescriptorId
ENTupleStructure
The fields in the RNTuple data model tree can carry different structural information about the type s...
ENTupleColumnType
__device__ AFloat max(AFloat x, AFloat y)
Definition Kernels.cuh:207