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 {
47using RNTupleSerializer = ROOT::Internal::RNTupleSerializer;
48
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
58 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
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)
71 flags |= RNTupleSerializer::kFlagRepetitiveField;
72 if (fieldDesc.IsProjectedField())
73 flags |= RNTupleSerializer::kFlagProjectedField;
74 if (fieldDesc.GetTypeChecksum().has_value())
75 flags |= RNTupleSerializer::kFlagHasTypeChecksum;
76 if (fieldDesc.IsSoACollection())
77 flags |= RNTupleSerializer::kFlagIsSoACollection;
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);
83 pos += RNTupleSerializer::SerializeString(fieldDesc.GetFieldDescription(), *where);
84
85 if (flags & RNTupleSerializer::kFlagRepetitiveField) {
86 pos += RNTupleSerializer::SerializeUInt64(fieldDesc.GetNRepetitions(), *where);
87 }
88 if (flags & RNTupleSerializer::kFlagProjectedField) {
89 pos += RNTupleSerializer::SerializeUInt32(onDiskProjectionSourceId, *where);
90 }
91 if (flags & RNTupleSerializer::kFlagHasTypeChecksum) {
92 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetTypeChecksum().value(), *where);
93 }
94
95 auto size = pos - base;
96 RNTupleSerializer::SerializeFramePostscript(base, size);
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();
118 for (auto fieldId : fieldList) {
119 const auto &f = desc.GetFieldDescriptor(fieldId);
120 auto onDiskParentId =
121 (f.GetParentId() == fieldZeroId) ? onDiskFieldId : context.GetOnDiskFieldId(f.GetParentId());
123 f.IsProjectedField() ? context.GetOnDiskFieldId(f.GetProjectionSourceId()) : ROOT::kInvalidDescriptorId;
125 pos += res.Unwrap();
126 } else {
127 return R__FORWARD_ERROR(res);
128 }
130 }
131
132 return pos - base;
133}
134
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 }
165 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldVersion);
166 bytes += RNTupleSerializer::DeserializeUInt32(bytes, typeVersion);
167 bytes += RNTupleSerializer::DeserializeUInt32(bytes, parentId);
168 if (auto res = RNTupleSerializer::DeserializeFieldStructure(bytes, structure)) {
169 bytes += res.Unwrap();
170 } else {
171 return R__FORWARD_ERROR(res);
172 }
173 bytes += RNTupleSerializer::DeserializeUInt16(bytes, flags);
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
202 if (flags & RNTupleSerializer::kFlagRepetitiveField) {
203 if (fnFrameSizeLeft() < sizeof(std::uint64_t))
204 return R__FAIL("field record frame too short");
205 std::uint64_t nRepetitions;
206 bytes += RNTupleSerializer::DeserializeUInt64(bytes, nRepetitions);
207 fieldDesc.NRepetitions(nRepetitions);
208 }
209
210 if (flags & RNTupleSerializer::kFlagProjectedField) {
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
218 if (flags & RNTupleSerializer::kFlagHasTypeChecksum) {
219 if (fnFrameSizeLeft() < sizeof(std::uint32_t))
220 return R__FAIL("field record frame too short");
221 std::uint32_t typeChecksum;
222 bytes += RNTupleSerializer::DeserializeUInt32(bytes, typeChecksum);
223 fieldDesc.TypeChecksum(typeChecksum);
224 }
225
226 if (flags & RNTupleSerializer::kFlagIsSoACollection) {
227 fieldDesc.IsSoACollection(true);
228 }
229
230 return frameSize;
231}
232
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
243 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
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())
254 flags |= RNTupleSerializer::kFlagDeferredColumn;
255 if (columnDesc.GetValueRange().has_value())
256 flags |= RNTupleSerializer::kFlagHasValueRange;
257 std::int64_t firstElementIdx = columnDesc.GetFirstElementIndex();
258 if (columnDesc.IsSuppressedDeferredColumn())
260 pos += RNTupleSerializer::SerializeUInt16(flags, *where);
261 pos += RNTupleSerializer::SerializeUInt16(columnDesc.GetRepresentationIndex(), *where);
262 if (flags & RNTupleSerializer::kFlagDeferredColumn)
263 pos += RNTupleSerializer::SerializeInt64(firstElementIdx, *where);
264 if (flags & RNTupleSerializer::kFlagHasValueRange) {
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
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
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 }
342 if (auto res = RNTupleSerializer::DeserializeColumnType(bytes, type)) {
343 bytes += res.Unwrap();
344 } else {
345 return R__FORWARD_ERROR(res);
346 }
347 bytes += RNTupleSerializer::DeserializeUInt16(bytes, bitsOnStorage);
348 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldId);
349 bytes += RNTupleSerializer::DeserializeUInt16(bytes, flags);
350 bytes += RNTupleSerializer::DeserializeUInt16(bytes, representationIndex);
351 if (flags & RNTupleSerializer::kFlagDeferredColumn) {
352 if (fnFrameSizeLeft() < sizeof(std::uint64_t))
353 return R__FAIL("column record frame too short");
354 bytes += RNTupleSerializer::DeserializeInt64(bytes, firstElementIdx);
355 }
356 if (flags & RNTupleSerializer::kFlagHasValueRange) {
357 if (fnFrameSizeLeft() < 2 * sizeof(std::uint64_t))
358 return R__FAIL("field record frame too short");
359 std::uint64_t minInt, maxInt;
360 bytes += RNTupleSerializer::DeserializeUInt64(bytes, minInt);
361 bytes += RNTupleSerializer::DeserializeUInt64(bytes, 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
377{
378 auto base = reinterpret_cast<unsigned char *>(buffer);
379 auto pos = base;
380 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
381
382 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
383
384 if (auto res = RNTupleSerializer::SerializeExtraTypeInfoId(desc.GetContentId(), *where)) {
385 pos += res.Unwrap();
386 } else {
387 return R__FORWARD_ERROR(res);
388 }
389 pos += RNTupleSerializer::SerializeUInt32(desc.GetTypeVersion(), *where);
390 pos += RNTupleSerializer::SerializeString(desc.GetTypeName(), *where);
391 pos += RNTupleSerializer::SerializeString(desc.GetContent(), *where);
392
393 auto size = pos - base;
394 RNTupleSerializer::SerializeFramePostscript(base, size);
395
396 return size;
397}
398
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()) {
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 }
435 result = RNTupleSerializer::DeserializeExtraTypeInfoId(bytes, contentId);
436 if (!result)
437 return R__FORWARD_ERROR(result);
438 bytes += result.Unwrap();
439 bytes += RNTupleSerializer::DeserializeUInt32(bytes, typeVersion);
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
453
454 return frameSize;
455}
456
457std::uint32_t SerializeLocatorPayloadLarge(const ROOT::RNTupleLocator &locator, unsigned char *buffer)
458{
459 if (buffer) {
460 RNTupleSerializer::SerializeUInt64(locator.GetNBytesOnStorage(), 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)) {
484 RNTupleSerializer::SerializeUInt32(locator.GetNBytesOnStorage(), buffer);
485 } else {
486 RNTupleSerializer::SerializeUInt64(locator.GetNBytesOnStorage(), buffer);
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,
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
515 const ROOT::Internal::RNTupleSerializer::RContext &context, void *buffer)
516{
517 R__ASSERT(columnDesc.IsAliasColumn());
518
519 auto base = reinterpret_cast<unsigned char *>(buffer);
520 auto pos = base;
521 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
522
523 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
524
525 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskColumnId(columnDesc.GetPhysicalId()), *where);
526 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskFieldId(columnDesc.GetFieldId()), *where);
527
528 pos += RNTupleSerializer::SerializeFramePostscript(buffer ? base : nullptr, pos - base).Unwrap();
529
530 return pos - base;
531}
532
534 std::span<const ROOT::DescriptorId_t> fieldList,
535 const ROOT::Internal::RNTupleSerializer::RContext &context, void *buffer,
537{
538 auto base = reinterpret_cast<unsigned char *>(buffer);
539 auto pos = base;
540 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
541
542 const auto *xHeader = !forHeaderExtension ? desc.GetHeaderExtension() : nullptr;
543
544 for (auto parentId : fieldList) {
545 if (xHeader && xHeader->ContainsField(parentId))
546 continue;
547
548 for (const auto &c : desc.GetColumnIterable(parentId)) {
549 if (!c.IsAliasColumn() || (xHeader && xHeader->ContainsExtendedColumnRepresentation(c.GetLogicalId())))
550 continue;
551
552 pos += SerializeAliasColumn(c, context, *where);
553 }
554 }
555
556 return pos - base;
557}
558
559ROOT::RResult<std::uint32_t> DeserializeAliasColumn(const void *buffer, std::uint64_t bufSize,
560 std::uint32_t &physicalColumnId, std::uint32_t &fieldId)
561{
562 auto base = reinterpret_cast<const unsigned char *>(buffer);
563 auto bytes = base;
564 std::uint64_t frameSize;
565 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
566 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
567 if (!result)
568 return R__FORWARD_ERROR(result);
569 bytes += result.Unwrap();
570
571 if (fnFrameSizeLeft() < 2 * sizeof(std::uint32_t)) {
572 return R__FAIL("alias column record frame too short");
573 }
574
575 bytes += RNTupleSerializer::DeserializeUInt32(bytes, physicalColumnId);
576 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldId);
577
578 return frameSize;
579}
580
581} // anonymous namespace
582
583std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeXxHash3(const unsigned char *data, std::uint64_t length,
584 std::uint64_t &xxhash3, void *buffer)
585{
586 if (buffer != nullptr) {
588 SerializeUInt64(xxhash3, buffer);
589 }
590 return 8;
591}
592
594 std::uint64_t &xxhash3)
595{
597 DeserializeUInt64(data + length, xxhash3);
598 if (xxhash3 != checksumReal)
599 return R__FAIL("XxHash-3 checksum mismatch");
600 return RResult<void>::Success();
601}
602
604{
605 std::uint64_t xxhash3;
606 return R__FORWARD_RESULT(VerifyXxHash3(data, length, xxhash3));
607}
608
609std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeInt16(std::int16_t val, void *buffer)
610{
611 if (buffer != nullptr) {
612 auto bytes = reinterpret_cast<unsigned char *>(buffer);
613 bytes[0] = (val & 0x00FF);
614 bytes[1] = (val & 0xFF00) >> 8;
615 }
616 return 2;
617}
618
619std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeInt16(const void *buffer, std::int16_t &val)
620{
621 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
622 val = std::int16_t(bytes[0]) + (std::int16_t(bytes[1]) << 8);
623 return 2;
624}
625
626std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeUInt16(std::uint16_t val, void *buffer)
627{
628 return SerializeInt16(val, buffer);
629}
630
631std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeUInt16(const void *buffer, std::uint16_t &val)
632{
633 return DeserializeInt16(buffer, *reinterpret_cast<std::int16_t *>(&val));
634}
635
636std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeInt32(std::int32_t val, void *buffer)
637{
638 if (buffer != nullptr) {
639 auto bytes = reinterpret_cast<unsigned char *>(buffer);
640 bytes[0] = (val & 0x000000FF);
641 bytes[1] = (val & 0x0000FF00) >> 8;
642 bytes[2] = (val & 0x00FF0000) >> 16;
643 bytes[3] = (val & 0xFF000000) >> 24;
644 }
645 return 4;
646}
647
648std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeInt32(const void *buffer, std::int32_t &val)
649{
650 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
651 val = std::int32_t(bytes[0]) + (std::int32_t(bytes[1]) << 8) + (std::int32_t(bytes[2]) << 16) +
652 (std::int32_t(bytes[3]) << 24);
653 return 4;
654}
655
656std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeUInt32(std::uint32_t val, void *buffer)
657{
658 return SerializeInt32(val, buffer);
659}
660
661std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeUInt32(const void *buffer, std::uint32_t &val)
662{
663 return DeserializeInt32(buffer, *reinterpret_cast<std::int32_t *>(&val));
664}
665
666std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeInt64(std::int64_t val, void *buffer)
667{
668 if (buffer != nullptr) {
669 auto bytes = reinterpret_cast<unsigned char *>(buffer);
670 bytes[0] = (val & 0x00000000000000FF);
671 bytes[1] = (val & 0x000000000000FF00) >> 8;
672 bytes[2] = (val & 0x0000000000FF0000) >> 16;
673 bytes[3] = (val & 0x00000000FF000000) >> 24;
674 bytes[4] = (val & 0x000000FF00000000) >> 32;
675 bytes[5] = (val & 0x0000FF0000000000) >> 40;
676 bytes[6] = (val & 0x00FF000000000000) >> 48;
677 bytes[7] = (val & 0xFF00000000000000) >> 56;
678 }
679 return 8;
680}
681
682std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeInt64(const void *buffer, std::int64_t &val)
683{
684 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
685 val = std::int64_t(bytes[0]) + (std::int64_t(bytes[1]) << 8) + (std::int64_t(bytes[2]) << 16) +
686 (std::int64_t(bytes[3]) << 24) + (std::int64_t(bytes[4]) << 32) + (std::int64_t(bytes[5]) << 40) +
687 (std::int64_t(bytes[6]) << 48) + (std::int64_t(bytes[7]) << 56);
688 return 8;
689}
690
691std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeUInt64(std::uint64_t val, void *buffer)
692{
693 return SerializeInt64(val, buffer);
694}
695
696std::uint32_t ROOT::Internal::RNTupleSerializer::DeserializeUInt64(const void *buffer, std::uint64_t &val)
697{
698 return DeserializeInt64(buffer, *reinterpret_cast<std::int64_t *>(&val));
699}
700
701std::uint32_t ROOT::Internal::RNTupleSerializer::SerializeString(const std::string &val, void *buffer)
702{
703 if (buffer) {
704 auto pos = reinterpret_cast<unsigned char *>(buffer);
705 pos += SerializeUInt32(val.length(), pos);
706 memcpy(pos, val.data(), val.length());
707 }
708 return sizeof(std::uint32_t) + val.length();
709}
710
712ROOT::Internal::RNTupleSerializer::DeserializeString(const void *buffer, std::uint64_t bufSize, std::string &val)
713{
714 if (bufSize < sizeof(std::uint32_t))
715 return R__FAIL("string buffer too short");
716 bufSize -= sizeof(std::uint32_t);
717
718 auto base = reinterpret_cast<const unsigned char *>(buffer);
719 auto bytes = base;
720 std::uint32_t length;
721 bytes += DeserializeUInt32(buffer, length);
722 if (bufSize < length)
723 return R__FAIL("string buffer too short");
724
725 val.resize(length);
726 memcpy(&val[0], bytes, length);
727 return sizeof(std::uint32_t) + length;
728}
729
732{
733 switch (type) {
734 case ENTupleColumnType::kBit: return SerializeUInt16(0x00, buffer);
735 case ENTupleColumnType::kByte: return SerializeUInt16(0x01, buffer);
736 case ENTupleColumnType::kChar: return SerializeUInt16(0x02, buffer);
737 case ENTupleColumnType::kInt8: return SerializeUInt16(0x03, buffer);
738 case ENTupleColumnType::kUInt8: return SerializeUInt16(0x04, buffer);
739 case ENTupleColumnType::kInt16: return SerializeUInt16(0x05, buffer);
740 case ENTupleColumnType::kUInt16: return SerializeUInt16(0x06, buffer);
741 case ENTupleColumnType::kInt32: return SerializeUInt16(0x07, buffer);
742 case ENTupleColumnType::kUInt32: return SerializeUInt16(0x08, buffer);
743 case ENTupleColumnType::kInt64: return SerializeUInt16(0x09, buffer);
744 case ENTupleColumnType::kUInt64: return SerializeUInt16(0x0A, buffer);
745 case ENTupleColumnType::kReal16: return SerializeUInt16(0x0B, buffer);
746 case ENTupleColumnType::kReal32: return SerializeUInt16(0x0C, buffer);
747 case ENTupleColumnType::kReal64: return SerializeUInt16(0x0D, buffer);
748 case ENTupleColumnType::kIndex32: return SerializeUInt16(0x0E, buffer);
749 case ENTupleColumnType::kIndex64: return SerializeUInt16(0x0F, buffer);
750 case ENTupleColumnType::kSwitch: return SerializeUInt16(0x10, buffer);
751 case ENTupleColumnType::kSplitInt16: return SerializeUInt16(0x11, buffer);
752 case ENTupleColumnType::kSplitUInt16: return SerializeUInt16(0x12, buffer);
753 case ENTupleColumnType::kSplitInt32: return SerializeUInt16(0x13, buffer);
754 case ENTupleColumnType::kSplitUInt32: return SerializeUInt16(0x14, buffer);
755 case ENTupleColumnType::kSplitInt64: return SerializeUInt16(0x15, buffer);
756 case ENTupleColumnType::kSplitUInt64: return SerializeUInt16(0x16, buffer);
757 case ENTupleColumnType::kSplitReal32: return SerializeUInt16(0x18, buffer);
758 case ENTupleColumnType::kSplitReal64: return SerializeUInt16(0x19, buffer);
759 case ENTupleColumnType::kSplitIndex32: return SerializeUInt16(0x1A, buffer);
760 case ENTupleColumnType::kSplitIndex64: return SerializeUInt16(0x1B, buffer);
761 case ENTupleColumnType::kReal32Trunc: return SerializeUInt16(0x1C, buffer);
762 case ENTupleColumnType::kReal32Quant: return SerializeUInt16(0x1D, buffer);
763 default:
765 return SerializeUInt16(0x99, buffer);
766 return R__FAIL("unexpected column type");
767 }
768}
769
772{
773 std::uint16_t onDiskType;
774 auto result = DeserializeUInt16(buffer, onDiskType);
775
776 switch (onDiskType) {
777 case 0x00: type = ENTupleColumnType::kBit; break;
778 case 0x01: type = ENTupleColumnType::kByte; break;
779 case 0x02: type = ENTupleColumnType::kChar; break;
780 case 0x03: type = ENTupleColumnType::kInt8; break;
781 case 0x04: type = ENTupleColumnType::kUInt8; break;
782 case 0x05: type = ENTupleColumnType::kInt16; break;
783 case 0x06: type = ENTupleColumnType::kUInt16; break;
784 case 0x07: type = ENTupleColumnType::kInt32; break;
785 case 0x08: type = ENTupleColumnType::kUInt32; break;
786 case 0x09: type = ENTupleColumnType::kInt64; break;
787 case 0x0A: type = ENTupleColumnType::kUInt64; break;
788 case 0x0B: type = ENTupleColumnType::kReal16; break;
789 case 0x0C: type = ENTupleColumnType::kReal32; break;
790 case 0x0D: type = ENTupleColumnType::kReal64; break;
791 case 0x0E: type = ENTupleColumnType::kIndex32; break;
792 case 0x0F: type = ENTupleColumnType::kIndex64; break;
793 case 0x10: type = ENTupleColumnType::kSwitch; break;
794 case 0x11: type = ENTupleColumnType::kSplitInt16; break;
795 case 0x12: type = ENTupleColumnType::kSplitUInt16; break;
796 case 0x13: type = ENTupleColumnType::kSplitInt32; break;
797 case 0x14: type = ENTupleColumnType::kSplitUInt32; break;
798 case 0x15: type = ENTupleColumnType::kSplitInt64; break;
799 case 0x16: type = ENTupleColumnType::kSplitUInt64; break;
800 case 0x18: type = ENTupleColumnType::kSplitReal32; break;
801 case 0x19: type = ENTupleColumnType::kSplitReal64; break;
802 case 0x1A: type = ENTupleColumnType::kSplitIndex32; break;
803 case 0x1B: type = ENTupleColumnType::kSplitIndex64; break;
804 case 0x1C: type = ENTupleColumnType::kReal32Trunc; break;
805 case 0x1D: type = ENTupleColumnType::kReal32Quant; break;
806 // case 0x99 => kTestFutureColumnType missing on purpose
807 default:
808 // may be a column type introduced by a future version
810 break;
811 }
812 return result;
813}
814
817{
819 switch (structure) {
820 case ENTupleStructure::kPlain: return SerializeUInt16(0x00, buffer);
821 case ENTupleStructure::kCollection: return SerializeUInt16(0x01, buffer);
822 case ENTupleStructure::kRecord: return SerializeUInt16(0x02, buffer);
823 case ENTupleStructure::kVariant: return SerializeUInt16(0x03, buffer);
824 case ENTupleStructure::kStreamer: return SerializeUInt16(0x04, buffer);
825 default:
827 return SerializeUInt16(0x99, buffer);
828 return R__FAIL("unexpected field structure type");
829 }
830}
831
834{
836 std::uint16_t onDiskValue;
837 auto result = DeserializeUInt16(buffer, onDiskValue);
838 switch (onDiskValue) {
839 case 0x00: structure = ENTupleStructure::kPlain; break;
840 case 0x01: structure = ENTupleStructure::kCollection; break;
841 case 0x02: structure = ENTupleStructure::kRecord; break;
842 case 0x03: structure = ENTupleStructure::kVariant; break;
843 case 0x04: structure = ENTupleStructure::kStreamer; break;
844 // case 0x99 => kTestFutureFieldStructure intentionally missing
845 default: structure = ENTupleStructure::kUnknown;
846 }
847 return result;
848}
849
852{
853 switch (id) {
854 case ROOT::EExtraTypeInfoIds::kStreamerInfo: return SerializeUInt32(0x00, buffer);
855 default: return R__FAIL("unexpected extra type info id");
856 }
857}
858
861{
862 std::uint32_t onDiskValue;
863 auto result = DeserializeUInt32(buffer, onDiskValue);
864 switch (onDiskValue) {
865 case 0x00: id = ROOT::EExtraTypeInfoIds::kStreamerInfo; break;
866 default:
868 R__LOG_DEBUG(0, ROOT::Internal::NTupleLog()) << "Unknown extra type info id: " << onDiskValue;
869 }
870 return result;
871}
872
874{
875 auto base = reinterpret_cast<unsigned char *>(buffer);
876 auto pos = base;
877 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
878
879 pos += SerializeUInt64(envelopeType, *where);
880 // The 48bits size information is filled in the postscript
881 return pos - base;
882}
883
885 std::uint64_t size,
886 std::uint64_t &xxhash3)
887{
888 if (size < sizeof(std::uint64_t))
889 return R__FAIL("envelope size too small");
890 if (size >= static_cast<uint64_t>(1) << 48)
891 return R__FAIL("envelope size too big");
892 if (envelope) {
893 std::uint64_t typeAndSize;
894 DeserializeUInt64(envelope, typeAndSize);
895 typeAndSize |= (size + 8) << 16;
896 SerializeUInt64(typeAndSize, envelope);
897 }
898 return SerializeXxHash3(envelope, size, xxhash3, envelope ? (envelope + size) : nullptr);
899}
900
903{
904 std::uint64_t xxhash3;
905 return R__FORWARD_RESULT(SerializeEnvelopePostscript(envelope, size, xxhash3));
906}
907
910 std::uint16_t expectedType, std::uint64_t &xxhash3)
911{
912 const std::uint64_t minEnvelopeSize = sizeof(std::uint64_t) + sizeof(std::uint64_t);
914 return R__FAIL("invalid envelope buffer, too short");
915
916 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
917 auto base = bytes;
918
919 std::uint64_t typeAndSize;
920 bytes += DeserializeUInt64(bytes, typeAndSize);
921
922 std::uint16_t envelopeType = typeAndSize & 0xFFFF;
923 if (envelopeType != expectedType) {
924 return R__FAIL("envelope type mismatch: expected " + std::to_string(expectedType) + ", found " +
925 std::to_string(envelopeType));
926 }
927
928 std::uint64_t envelopeSize = typeAndSize >> 16;
929 if (bufSize < envelopeSize)
930 return R__FAIL("envelope buffer size too small");
932 return R__FAIL("invalid envelope, too short");
933
934 auto result = VerifyXxHash3(base, envelopeSize - 8, xxhash3);
935 if (!result)
936 return R__FORWARD_ERROR(result);
937
938 return sizeof(typeAndSize);
939}
940
942 std::uint64_t bufSize,
943 std::uint16_t expectedType)
944{
945 std::uint64_t xxhash3;
946 return R__FORWARD_RESULT(DeserializeEnvelope(buffer, bufSize, expectedType, xxhash3));
947}
948
950{
951 // Marker: multiply the final size with 1
952 return SerializeInt64(1, buffer);
953}
954
956{
957 auto base = reinterpret_cast<unsigned char *>(buffer);
958 auto pos = base;
959 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
960
961 // Marker: multiply the final size with -1
962 pos += SerializeInt64(-1, *where);
963 pos += SerializeUInt32(nitems, *where);
964 return pos - base;
965}
966
969{
970 auto preambleSize = sizeof(std::int64_t);
971 if (size < preambleSize)
972 return R__FAIL("frame too short: " + std::to_string(size));
973 if (frame) {
974 std::int64_t marker;
975 DeserializeInt64(frame, marker);
976 if ((marker < 0) && (size < (sizeof(std::uint32_t) + preambleSize)))
977 return R__FAIL("frame too short: " + std::to_string(size));
978 SerializeInt64(marker * static_cast<int64_t>(size), frame);
979 }
980 return 0;
981}
982
985 std::uint64_t &frameSize, std::uint32_t &nitems)
986{
987 std::uint64_t minSize = sizeof(std::int64_t);
988 if (bufSize < minSize)
989 return R__FAIL("frame too short");
990
991 std::int64_t *ssize = reinterpret_cast<std::int64_t *>(&frameSize);
992 DeserializeInt64(buffer, *ssize);
993
994 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
995 bytes += minSize;
996
997 if (*ssize >= 0) {
998 // Record frame
999 nitems = 1;
1000 } else {
1001 // List frame
1002 minSize += sizeof(std::uint32_t);
1003 if (bufSize < minSize)
1004 return R__FAIL("frame too short");
1005 bytes += DeserializeUInt32(bytes, nitems);
1006 *ssize = -(*ssize);
1007 }
1008
1009 if (frameSize < minSize)
1010 return R__FAIL("corrupt frame size");
1011 if (bufSize < frameSize)
1012 return R__FAIL("frame too short");
1013
1014 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1015}
1016
1018 std::uint64_t bufSize,
1019 std::uint64_t &frameSize)
1020{
1021 std::uint32_t nitems;
1022 return R__FORWARD_RESULT(DeserializeFrameHeader(buffer, bufSize, frameSize, nitems));
1023}
1024
1026ROOT::Internal::RNTupleSerializer::SerializeFeatureFlags(const std::vector<std::uint64_t> &flags, void *buffer)
1027{
1028 if (flags.empty())
1029 return SerializeUInt64(0, buffer);
1030
1031 if (buffer) {
1032 auto bytes = reinterpret_cast<unsigned char *>(buffer);
1033
1034 for (unsigned i = 0; i < flags.size(); ++i) {
1035 if (flags[i] & 0x8000000000000000)
1036 return R__FAIL("feature flag out of bounds");
1037
1038 // The MSb indicates that another Int64 follows; set this bit to 1 for all except the last element
1039 if (i == (flags.size() - 1))
1040 SerializeUInt64(flags[i], bytes);
1041 else
1042 bytes += SerializeUInt64(flags[i] | 0x8000000000000000, bytes);
1043 }
1044 }
1045 return (flags.size() * sizeof(std::int64_t));
1046}
1047
1050 std::vector<std::uint64_t> &flags)
1051{
1052 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1053
1054 flags.clear();
1055 std::uint64_t f;
1056 do {
1057 if (bufSize < sizeof(std::uint64_t))
1058 return R__FAIL("feature flag buffer too short");
1059 bytes += DeserializeUInt64(bytes, f);
1060 bufSize -= sizeof(std::uint64_t);
1061 flags.emplace_back(f & ~0x8000000000000000);
1062 } while (f & 0x8000000000000000);
1063
1064 return (flags.size() * sizeof(std::uint64_t));
1065}
1066
1069{
1071 return R__FAIL("locator is not serializable");
1072
1073 std::uint32_t size = 0;
1074 if ((locator.GetType() == RNTupleLocator::kTypeFile) &&
1075 (locator.GetNBytesOnStorage() <= std::numeric_limits<std::int32_t>::max())) {
1076 size += SerializeUInt32(locator.GetNBytesOnStorage(), buffer);
1077 size += SerializeUInt64(locator.GetPosition<std::uint64_t>(),
1078 buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
1079 return size;
1080 }
1081
1082 std::uint8_t locatorType = 0;
1083 auto payloadp = buffer ? reinterpret_cast<unsigned char *>(buffer) + sizeof(std::int32_t) : nullptr;
1084 switch (locator.GetType()) {
1087 locatorType = 0x01;
1088 break;
1091 locatorType = 0x02;
1092 break;
1095 locatorType = 0x03;
1096 break;
1097 default:
1098 if (locator.GetType() == ROOT::Internal::kTestLocatorType) {
1099 // For the testing locator, use the same payload format as Object64. We won't read it back anyway.
1100 RNTupleLocator dummy;
1103 locatorType = 0x7e;
1104 } else {
1105 return R__FAIL("locator has unknown type");
1106 }
1107 }
1108 std::int32_t head = sizeof(std::int32_t) + size;
1109 head |= locator.GetReserved() << 16;
1110 head |= static_cast<int>(locatorType & 0x7F) << 24;
1111 head = -head;
1112 size += RNTupleSerializer::SerializeInt32(head, buffer);
1113 return size;
1114}
1115
1117 std::uint64_t bufSize,
1119{
1120 if (bufSize < sizeof(std::int32_t))
1121 return R__FAIL("too short locator");
1122
1123 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1124 std::int32_t head;
1125
1126 bytes += DeserializeInt32(bytes, head);
1127 bufSize -= sizeof(std::int32_t);
1128 if (head < 0) {
1129 head = -head;
1130 const int type = head >> 24;
1131 const std::uint32_t payloadSize = (static_cast<std::uint32_t>(head) & 0x0000FFFF) - sizeof(std::int32_t);
1132 if (bufSize < payloadSize)
1133 return R__FAIL("too short locator");
1134
1135 locator.SetReserved(static_cast<std::uint32_t>(head >> 16) & 0xFF);
1136 switch (type) {
1137 case 0x01:
1140 break;
1141 case 0x02:
1144 break;
1145 case 0x03:
1148 break;
1149 default: locator.SetType(RNTupleLocator::kTypeUnknown);
1150 }
1151 bytes += payloadSize;
1152 } else {
1153 if (bufSize < sizeof(std::uint64_t))
1154 return R__FAIL("too short locator");
1155 std::uint64_t offset;
1156 bytes += DeserializeUInt64(bytes, offset);
1158 locator.SetNBytesOnStorage(head);
1159 locator.SetPosition(offset);
1160 }
1161
1162 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1163}
1164
1167{
1168 auto size = SerializeUInt64(envelopeLink.fLength, buffer);
1169 auto res =
1170 SerializeLocator(envelopeLink.fLocator, buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
1171 if (res)
1172 size += res.Unwrap();
1173 else
1174 return R__FORWARD_ERROR(res);
1175 return size;
1176}
1177
1179 std::uint64_t bufSize,
1181{
1182 if (bufSize < sizeof(std::int64_t))
1183 return R__FAIL("too short envelope link");
1184
1185 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1186 bytes += DeserializeUInt64(bytes, envelopeLink.fLength);
1187 bufSize -= sizeof(std::uint64_t);
1188 if (auto res = DeserializeLocator(bytes, bufSize, envelopeLink.fLocator)) {
1189 bytes += res.Unwrap();
1190 } else {
1191 return R__FORWARD_ERROR(res);
1192 }
1193 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1194}
1195
1198{
1199 if (clusterSummary.fNEntries >= (static_cast<std::uint64_t>(1) << 56)) {
1200 return R__FAIL("number of entries in cluster exceeds maximum of 2^56");
1201 }
1202
1203 auto base = reinterpret_cast<unsigned char *>(buffer);
1204 auto pos = base;
1205 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1206
1207 auto frame = pos;
1208 pos += SerializeRecordFramePreamble(*where);
1209 pos += SerializeUInt64(clusterSummary.fFirstEntry, *where);
1210 const std::uint64_t nEntriesAndFlags =
1211 (static_cast<std::uint64_t>(clusterSummary.fFlags) << 56) | clusterSummary.fNEntries;
1212 pos += SerializeUInt64(nEntriesAndFlags, *where);
1213
1214 auto size = pos - frame;
1215 if (auto res = SerializeFramePostscript(frame, size)) {
1216 pos += res.Unwrap();
1217 } else {
1218 return R__FORWARD_ERROR(res);
1219 }
1220 return size;
1221}
1222
1226{
1227 auto base = reinterpret_cast<const unsigned char *>(buffer);
1228 auto bytes = base;
1229 std::uint64_t frameSize;
1230 if (auto res = DeserializeFrameHeader(bytes, bufSize, frameSize)) {
1231 bytes += res.Unwrap();
1232 } else {
1233 return R__FORWARD_ERROR(res);
1234 }
1235
1236 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
1237 if (fnFrameSizeLeft() < 2 * sizeof(std::uint64_t))
1238 return R__FAIL("too short cluster summary");
1239
1240 bytes += DeserializeUInt64(bytes, clusterSummary.fFirstEntry);
1241 std::uint64_t nEntriesAndFlags;
1242 bytes += DeserializeUInt64(bytes, nEntriesAndFlags);
1243
1244 const std::uint64_t nEntries = (nEntriesAndFlags << 8) >> 8;
1245 const std::uint8_t flags = nEntriesAndFlags >> 56;
1246
1247 if (flags & 0x01) {
1248 return R__FAIL("sharded cluster flag set in cluster summary; sharded clusters are currently unsupported.");
1249 }
1250
1251 clusterSummary.fNEntries = nEntries;
1252 clusterSummary.fFlags = flags;
1253
1254 return frameSize;
1255}
1256
1259{
1260 auto base = reinterpret_cast<unsigned char *>(buffer);
1261 auto pos = base;
1262 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1263
1264 auto frame = pos;
1265 pos += SerializeRecordFramePreamble(*where);
1266 pos += SerializeUInt64(clusterGroup.fMinEntry, *where);
1267 pos += SerializeUInt64(clusterGroup.fEntrySpan, *where);
1268 pos += SerializeUInt32(clusterGroup.fNClusters, *where);
1269 if (auto res = SerializeEnvelopeLink(clusterGroup.fPageListEnvelopeLink, *where)) {
1270 pos += res.Unwrap();
1271 } else {
1272 return R__FORWARD_ERROR(res);
1273 }
1274 auto size = pos - frame;
1275 if (auto res = SerializeFramePostscript(frame, size)) {
1276 return size;
1277 } else {
1278 return R__FORWARD_ERROR(res);
1279 }
1280}
1281
1283 std::uint64_t bufSize,
1285{
1286 auto base = reinterpret_cast<const unsigned char *>(buffer);
1287 auto bytes = base;
1288
1289 std::uint64_t frameSize;
1290 if (auto res = DeserializeFrameHeader(bytes, bufSize, frameSize)) {
1291 bytes += res.Unwrap();
1292 } else {
1293 return R__FORWARD_ERROR(res);
1294 }
1295
1296 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
1297 if (fnFrameSizeLeft() < sizeof(std::uint32_t) + 2 * sizeof(std::uint64_t))
1298 return R__FAIL("too short cluster group");
1299
1300 bytes += DeserializeUInt64(bytes, clusterGroup.fMinEntry);
1301 bytes += DeserializeUInt64(bytes, clusterGroup.fEntrySpan);
1302 bytes += DeserializeUInt32(bytes, clusterGroup.fNClusters);
1303 if (auto res = DeserializeEnvelopeLink(bytes, fnFrameSizeLeft(), clusterGroup.fPageListEnvelopeLink)) {
1304 bytes += res.Unwrap();
1305 } else {
1306 return R__FORWARD_ERROR(res);
1307 }
1308
1309 return frameSize;
1310}
1311
1313 bool forHeaderExtension)
1314{
1315 auto fieldZeroId = desc.GetFieldZeroId();
1316 auto depthFirstTraversal = [&](std::span<ROOT::DescriptorId_t> fieldTrees, auto doForEachField) {
1317 std::deque<ROOT::DescriptorId_t> idQueue{fieldTrees.begin(), fieldTrees.end()};
1318 while (!idQueue.empty()) {
1319 auto fieldId = idQueue.front();
1320 idQueue.pop_front();
1321 // Field zero has no physical representation nor columns of its own; recurse over its subfields only
1322 if (fieldId != fieldZeroId)
1324 unsigned i = 0;
1325 for (const auto &f : desc.GetFieldIterable(fieldId))
1326 idQueue.insert(idQueue.begin() + i++, f.GetId());
1327 }
1328 };
1329
1330 R__ASSERT(desc.GetNFields() > 0); // we must have at least a zero field
1331
1332 std::vector<ROOT::DescriptorId_t> fieldTrees;
1333 if (!forHeaderExtension) {
1334 fieldTrees.emplace_back(fieldZeroId);
1335 } else if (auto xHeader = desc.GetHeaderExtension()) {
1336 fieldTrees = xHeader->GetTopMostFields(desc);
1337 }
1340 for (const auto &c : desc.GetColumnIterable(fieldId)) {
1341 if (!c.IsAliasColumn()) {
1342 MapPhysicalColumnId(c.GetPhysicalId());
1343 }
1344 }
1345 });
1346
1347 if (forHeaderExtension) {
1348 // Create physical IDs for column representations that extend fields of the regular header.
1349 // First the physical columns then the alias columns.
1350 for (auto memId : desc.GetHeaderExtension()->GetExtendedColumnRepresentations()) {
1351 const auto &columnDesc = desc.GetColumnDescriptor(memId);
1352 if (!columnDesc.IsAliasColumn()) {
1353 MapPhysicalColumnId(columnDesc.GetPhysicalId());
1354 }
1355 }
1356 }
1357}
1358
1361 const RContext &context, bool forHeaderExtension)
1362{
1363 auto base = reinterpret_cast<unsigned char *>(buffer);
1364 auto pos = base;
1365 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1366
1367 std::size_t nFields = 0, nColumns = 0, nAliasColumns = 0, fieldListOffset = 0;
1368 // Columns in the extension header that are attached to a field of the regular header
1369 std::vector<std::reference_wrapper<const ROOT::RColumnDescriptor>> extraColumns;
1370 if (forHeaderExtension) {
1371 // A call to `RNTupleDescriptorBuilder::BeginHeaderExtension()` is not strictly required after serializing the
1372 // header, which may happen, e.g., in unit tests. Ensure an empty schema extension is serialized in this case
1373 if (auto xHeader = desc.GetHeaderExtension()) {
1374 nFields = xHeader->GetNFields();
1375 nColumns = xHeader->GetNPhysicalColumns();
1376 nAliasColumns = xHeader->GetNLogicalColumns() - xHeader->GetNPhysicalColumns();
1377 fieldListOffset = desc.GetNFields() - nFields - 1;
1378
1379 extraColumns.reserve(xHeader->GetExtendedColumnRepresentations().size());
1380 for (auto columnId : xHeader->GetExtendedColumnRepresentations()) {
1381 extraColumns.emplace_back(desc.GetColumnDescriptor(columnId));
1382 }
1383 }
1384 } else {
1385 if (auto xHeader = desc.GetHeaderExtension()) {
1386 nFields = desc.GetNFields() - xHeader->GetNFields() - 1;
1387 nColumns = desc.GetNPhysicalColumns() - xHeader->GetNPhysicalColumns();
1389 (xHeader->GetNLogicalColumns() - xHeader->GetNPhysicalColumns());
1390 } else {
1391 nFields = desc.GetNFields() - 1;
1394 }
1395 }
1396 const auto nExtraTypeInfos = desc.GetNExtraTypeInfos();
1397 const auto &onDiskFields = context.GetOnDiskFieldList();
1399 std::span<const ROOT::DescriptorId_t> fieldList{onDiskFields.data() + fieldListOffset, nFields};
1400
1401 auto frame = pos;
1402 pos += SerializeListFramePreamble(nFields, *where);
1403 if (auto res = SerializeFieldList(desc, fieldList, /*firstOnDiskId=*/fieldListOffset, context, *where)) {
1404 pos += res.Unwrap();
1405 } else {
1406 return R__FORWARD_ERROR(res);
1407 }
1408 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1409 pos += res.Unwrap();
1410 } else {
1411 return R__FORWARD_ERROR(res);
1412 }
1413
1414 frame = pos;
1415 pos += SerializeListFramePreamble(nColumns, *where);
1416 if (auto res = SerializeColumnsOfFields(desc, fieldList, context, *where, forHeaderExtension)) {
1417 pos += res.Unwrap();
1418 } else {
1419 return R__FORWARD_ERROR(res);
1420 }
1421 for (const auto &c : extraColumns) {
1422 if (!c.get().IsAliasColumn()) {
1423 if (auto res = SerializePhysicalColumn(c.get(), context, *where)) {
1424 pos += res.Unwrap();
1425 } else {
1426 return R__FORWARD_ERROR(res);
1427 }
1428 }
1429 }
1430 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1431 pos += res.Unwrap();
1432 } else {
1433 return R__FORWARD_ERROR(res);
1434 }
1435
1436 frame = pos;
1437 pos += SerializeListFramePreamble(nAliasColumns, *where);
1439 for (const auto &c : extraColumns) {
1440 if (c.get().IsAliasColumn()) {
1441 pos += SerializeAliasColumn(c.get(), context, *where);
1442 }
1443 }
1444 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1445 pos += res.Unwrap();
1446 } else {
1447 return R__FORWARD_ERROR(res);
1448 }
1449
1450 frame = pos;
1451 // We only serialize the extra type info list in the header extension.
1452 if (forHeaderExtension) {
1453 pos += SerializeListFramePreamble(nExtraTypeInfos, *where);
1454 if (auto res = SerializeExtraTypeInfoList(desc, *where)) {
1455 pos += res.Unwrap();
1456 } else {
1457 return R__FORWARD_ERROR(res);
1458 }
1459 } else {
1460 pos += SerializeListFramePreamble(0, *where);
1461 }
1462 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1463 pos += res.Unwrap();
1464 } else {
1465 return R__FORWARD_ERROR(res);
1466 }
1467
1468 return static_cast<std::uint32_t>(pos - base);
1469}
1470
1474{
1475 auto base = reinterpret_cast<const unsigned char *>(buffer);
1476 auto bytes = base;
1477 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1478
1479 std::uint64_t frameSize;
1480 auto frame = bytes;
1481 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
1482
1483 std::uint32_t nFields;
1484 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nFields)) {
1485 bytes += res.Unwrap();
1486 } else {
1487 return R__FORWARD_ERROR(res);
1488 }
1489 // The zero field is always added before `DeserializeSchemaDescription()` is called
1490 const std::uint32_t fieldIdRangeBegin = descBuilder.GetDescriptor().GetNFields() - 1;
1491 for (unsigned i = 0; i < nFields; ++i) {
1492 std::uint32_t fieldId = fieldIdRangeBegin + i;
1494 if (auto res = DeserializeField(bytes, fnFrameSizeLeft(), fieldBuilder)) {
1495 bytes += res.Unwrap();
1496 } else {
1497 return R__FORWARD_ERROR(res);
1498 }
1499 if (fieldId == fieldBuilder.GetParentId())
1500 fieldBuilder.ParentId(kZeroFieldId);
1501 auto fieldDesc = fieldBuilder.FieldId(fieldId).MakeDescriptor();
1502 if (!fieldDesc)
1504 const auto parentId = fieldDesc.Inspect().GetParentId();
1505 const auto projectionSourceId = fieldDesc.Inspect().GetProjectionSourceId();
1506 descBuilder.AddField(fieldDesc.Unwrap());
1507 auto resVoid = descBuilder.AddFieldLink(parentId, fieldId);
1508 if (!resVoid)
1509 return R__FORWARD_ERROR(resVoid);
1511 resVoid = descBuilder.AddFieldProjection(projectionSourceId, fieldId);
1512 if (!resVoid)
1513 return R__FORWARD_ERROR(resVoid);
1514 }
1515 }
1516 bytes = frame + frameSize;
1517
1518 // As columns are added in order of representation index and column index, determine the column index
1519 // for the currently deserialized column from the columns already added.
1521 std::uint16_t representationIndex) -> std::uint32_t {
1522 const auto &existingColumns = descBuilder.GetDescriptor().GetFieldDescriptor(fieldId).GetLogicalColumnIds();
1523 if (existingColumns.empty())
1524 return 0;
1525 const auto &lastColumnDesc = descBuilder.GetDescriptor().GetColumnDescriptor(existingColumns.back());
1526 return (representationIndex == lastColumnDesc.GetRepresentationIndex()) ? (lastColumnDesc.GetIndex() + 1) : 0;
1527 };
1528
1529 std::uint32_t nColumns;
1530 frame = bytes;
1531 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nColumns)) {
1532 bytes += res.Unwrap();
1533 } else {
1534 return R__FORWARD_ERROR(res);
1535 }
1536
1537 if (descBuilder.GetDescriptor().GetNLogicalColumns() > descBuilder.GetDescriptor().GetNPhysicalColumns())
1538 descBuilder.ShiftAliasColumns(nColumns);
1539
1540 const std::uint32_t columnIdRangeBegin = descBuilder.GetDescriptor().GetNPhysicalColumns();
1541 for (unsigned i = 0; i < nColumns; ++i) {
1542 std::uint32_t columnId = columnIdRangeBegin + i;
1545 bytes += res.Unwrap();
1546 } else {
1547 return R__FORWARD_ERROR(res);
1548 }
1549
1550 columnBuilder.Index(fnNextColumnIndex(columnBuilder.GetFieldId(), columnBuilder.GetRepresentationIndex()));
1551 columnBuilder.LogicalColumnId(columnId);
1552 columnBuilder.PhysicalColumnId(columnId);
1553 auto columnDesc = columnBuilder.MakeDescriptor();
1554 if (!columnDesc)
1556 auto resVoid = descBuilder.AddColumn(columnDesc.Unwrap());
1557 if (!resVoid)
1558 return R__FORWARD_ERROR(resVoid);
1559 }
1560 bytes = frame + frameSize;
1561
1562 std::uint32_t nAliasColumns;
1563 frame = bytes;
1564 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nAliasColumns)) {
1565 bytes += res.Unwrap();
1566 } else {
1567 return R__FORWARD_ERROR(res);
1568 }
1569 const std::uint32_t aliasColumnIdRangeBegin = descBuilder.GetDescriptor().GetNLogicalColumns();
1570 for (unsigned i = 0; i < nAliasColumns; ++i) {
1571 std::uint32_t physicalId;
1572 std::uint32_t fieldId;
1574 bytes += res.Unwrap();
1575 } else {
1576 return R__FORWARD_ERROR(res);
1577 }
1578
1580 columnBuilder.LogicalColumnId(aliasColumnIdRangeBegin + i).PhysicalColumnId(physicalId).FieldId(fieldId);
1581 const auto &physicalColumnDesc = descBuilder.GetDescriptor().GetColumnDescriptor(physicalId);
1582 columnBuilder.BitsOnStorage(physicalColumnDesc.GetBitsOnStorage());
1583 columnBuilder.ValueRange(physicalColumnDesc.GetValueRange());
1584 columnBuilder.Type(physicalColumnDesc.GetType());
1585 columnBuilder.RepresentationIndex(physicalColumnDesc.GetRepresentationIndex());
1586 columnBuilder.Index(fnNextColumnIndex(columnBuilder.GetFieldId(), columnBuilder.GetRepresentationIndex()));
1587
1588 auto aliasColumnDesc = columnBuilder.MakeDescriptor();
1589 if (!aliasColumnDesc)
1591 auto resVoid = descBuilder.AddColumn(aliasColumnDesc.Unwrap());
1592 if (!resVoid)
1593 return R__FORWARD_ERROR(resVoid);
1594 }
1595 bytes = frame + frameSize;
1596
1597 std::uint32_t nExtraTypeInfos;
1598 frame = bytes;
1599 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nExtraTypeInfos)) {
1600 bytes += res.Unwrap();
1601 } else {
1602 return R__FORWARD_ERROR(res);
1603 }
1604 for (unsigned i = 0; i < nExtraTypeInfos; ++i) {
1607 bytes += res.Unwrap();
1608 } else {
1609 return R__FORWARD_ERROR(res);
1610 }
1611
1612 auto extraTypeInfoDesc = extraTypeInfoBuilder.MoveDescriptor();
1613 // We ignore unknown extra type information
1615 descBuilder.AddExtraTypeInfo(extraTypeInfoDesc.Unwrap());
1616 }
1617 bytes = frame + frameSize;
1618
1619 return bytes - base;
1620}
1621
1624{
1625 RContext context;
1626
1627 auto base = reinterpret_cast<unsigned char *>(buffer);
1628 auto pos = base;
1629 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1630
1631 pos += SerializeEnvelopePreamble(kEnvelopeTypeHeader, *where);
1632 if (auto res = SerializeFeatureFlags(desc.GetFeatureFlags(), *where)) {
1633 pos += res.Unwrap();
1634 } else {
1635 return R__FORWARD_ERROR(res);
1636 }
1637 pos += SerializeString(desc.GetName(), *where);
1638 pos += SerializeString(desc.GetDescription(), *where);
1639 pos += SerializeString(std::string("ROOT v") + ROOT_RELEASE, *where);
1640
1641 context.MapSchema(desc, /*forHeaderExtension=*/false);
1642
1643 if (auto res = SerializeSchemaDescription(*where, desc, context)) {
1644 pos += res.Unwrap();
1645 } else {
1646 return R__FORWARD_ERROR(res);
1647 }
1648
1649 std::uint64_t size = pos - base;
1650 std::uint64_t xxhash3 = 0;
1651 if (auto res = SerializeEnvelopePostscript(base, size, xxhash3)) {
1652 size += res.Unwrap();
1653 } else {
1654 return R__FORWARD_ERROR(res);
1655 }
1656
1657 context.SetHeaderSize(size);
1658 context.SetHeaderXxHash3(xxhash3);
1659 return context;
1660}
1661
1664 std::span<ROOT::DescriptorId_t> physClusterIDs,
1665 const RContext &context)
1666{
1667 auto base = reinterpret_cast<unsigned char *>(buffer);
1668 auto pos = base;
1669 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1670
1671 pos += SerializeEnvelopePreamble(kEnvelopeTypePageList, *where);
1672
1673 pos += SerializeUInt64(context.GetHeaderXxHash3(), *where);
1674
1675 // Cluster summaries
1676 const auto nClusters = physClusterIDs.size();
1677 auto clusterSummaryFrame = pos;
1678 pos += SerializeListFramePreamble(nClusters, *where);
1679 for (auto clusterId : physClusterIDs) {
1680 const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1681 RClusterSummary summary{clusterDesc.GetFirstEntryIndex(), clusterDesc.GetNEntries(), 0};
1682 if (auto res = SerializeClusterSummary(summary, *where)) {
1683 pos += res.Unwrap();
1684 } else {
1685 return R__FORWARD_ERROR(res);
1686 }
1687 }
1688 if (auto res = SerializeFramePostscript(buffer ? clusterSummaryFrame : nullptr, pos - clusterSummaryFrame)) {
1689 pos += res.Unwrap();
1690 } else {
1691 return R__FORWARD_ERROR(res);
1692 }
1693
1694 // Page locations
1695 auto topMostFrame = pos;
1696 pos += SerializeListFramePreamble(nClusters, *where);
1697
1698 for (auto clusterId : physClusterIDs) {
1699 const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1700 // Get an ordered set of physical column ids
1701 std::set<ROOT::DescriptorId_t> onDiskColumnIds;
1702 for (const auto &columnRange : clusterDesc.GetColumnRangeIterable())
1703 onDiskColumnIds.insert(context.GetOnDiskColumnId(columnRange.GetPhysicalColumnId()));
1704
1705 auto outerFrame = pos;
1706 pos += SerializeListFramePreamble(onDiskColumnIds.size(), *where);
1707 for (auto onDiskId : onDiskColumnIds) {
1708 auto memId = context.GetMemColumnId(onDiskId);
1709 const auto &columnRange = clusterDesc.GetColumnRange(memId);
1710
1711 auto innerFrame = pos;
1712 if (columnRange.IsSuppressed()) {
1713 // Empty page range
1714 pos += SerializeListFramePreamble(0, *where);
1715 pos += SerializeInt64(kSuppressedColumnMarker, *where);
1716 } else {
1717 const auto &pageRange = clusterDesc.GetPageRange(memId);
1718 pos += SerializeListFramePreamble(pageRange.GetPageInfos().size(), *where);
1719
1720 for (const auto &pi : pageRange.GetPageInfos()) {
1721 std::int32_t nElements =
1722 pi.HasChecksum() ? -static_cast<std::int32_t>(pi.GetNElements()) : pi.GetNElements();
1723 pos += SerializeUInt32(nElements, *where);
1724 if (auto res = SerializeLocator(pi.GetLocator(), *where)) {
1725 pos += res.Unwrap();
1726 } else {
1727 return R__FORWARD_ERROR(res);
1728 }
1729 }
1730 pos += SerializeInt64(columnRange.GetFirstElementIndex(), *where);
1731 pos += SerializeUInt32(columnRange.GetCompressionSettings().value(), *where);
1732 }
1733
1734 if (auto res = SerializeFramePostscript(buffer ? innerFrame : nullptr, pos - innerFrame)) {
1735 pos += res.Unwrap();
1736 } else {
1737 return R__FORWARD_ERROR(res);
1738 }
1739 }
1740 if (auto res = SerializeFramePostscript(buffer ? outerFrame : nullptr, pos - outerFrame)) {
1741 pos += res.Unwrap();
1742 } else {
1743 return R__FORWARD_ERROR(res);
1744 }
1745 }
1746
1747 if (auto res = SerializeFramePostscript(buffer ? topMostFrame : nullptr, pos - topMostFrame)) {
1748 pos += res.Unwrap();
1749 } else {
1750 return R__FORWARD_ERROR(res);
1751 }
1752 std::uint64_t size = pos - base;
1753 if (auto res = SerializeEnvelopePostscript(base, size)) {
1754 size += res.Unwrap();
1755 } else {
1756 return R__FORWARD_ERROR(res);
1757 }
1758 return size;
1759}
1760
1762 const ROOT::RNTupleDescriptor &desc,
1763 const RContext &context)
1764{
1765 auto base = reinterpret_cast<unsigned char *>(buffer);
1766 auto pos = base;
1767 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1768
1769 pos += SerializeEnvelopePreamble(kEnvelopeTypeFooter, *where);
1770
1771 // NOTE: we currently serialize all feature flags in the footer, even those that were already written in the
1772 // header. This is fine, as they will be logically OR-ed together during deserialization.
1773 if (auto res = SerializeFeatureFlags(desc.GetFeatureFlags(), *where)) {
1774 pos += res.Unwrap();
1775 } else {
1776 return R__FORWARD_ERROR(res);
1777 }
1778 pos += SerializeUInt64(context.GetHeaderXxHash3(), *where);
1779
1780 // Schema extension, i.e. incremental changes with respect to the header
1781 auto frame = pos;
1782 pos += SerializeRecordFramePreamble(*where);
1783 if (auto res = SerializeSchemaDescription(*where, desc, context, /*forHeaderExtension=*/true)) {
1784 pos += res.Unwrap();
1785 } else {
1786 return R__FORWARD_ERROR(res);
1787 }
1788 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1789 pos += res.Unwrap();
1790 } else {
1791 return R__FORWARD_ERROR(res);
1792 }
1793
1794 // Cluster groups
1795 frame = pos;
1796 const auto nClusterGroups = desc.GetNClusterGroups();
1797 pos += SerializeListFramePreamble(nClusterGroups, *where);
1798 for (unsigned int i = 0; i < nClusterGroups; ++i) {
1799 const auto &cgDesc = desc.GetClusterGroupDescriptor(context.GetMemClusterGroupId(i));
1801 clusterGroup.fMinEntry = cgDesc.GetMinEntry();
1802 clusterGroup.fEntrySpan = cgDesc.GetEntrySpan();
1803 clusterGroup.fNClusters = cgDesc.GetNClusters();
1804 clusterGroup.fPageListEnvelopeLink.fLength = cgDesc.GetPageListLength();
1805 clusterGroup.fPageListEnvelopeLink.fLocator = cgDesc.GetPageListLocator();
1806 if (auto res = SerializeClusterGroup(clusterGroup, *where)) {
1807 pos += res.Unwrap();
1808 } else {
1809 return R__FORWARD_ERROR(res);
1810 }
1811 }
1812 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1813 pos += res.Unwrap();
1814 } else {
1815 return R__FORWARD_ERROR(res);
1816 }
1817
1818 // Attributes
1819 frame = pos;
1820 const auto nAttributeSets = desc.GetNAttributeSets();
1821 if (nAttributeSets > 0) {
1822 R__LOG_WARNING(NTupleLog()) << "RNTuple Attributes are experimental. They are not guaranteed to be readable "
1823 "back in the future (but your main data is)";
1824 }
1825 pos += SerializeListFramePreamble(nAttributeSets, *where);
1826 for (const auto &attrSet : desc.GetAttrSetIterable()) {
1827 if (auto res = SerializeAttributeSet(attrSet, *where)) {
1828 pos += res.Unwrap();
1829 } else {
1830 return R__FORWARD_ERROR(res);
1831 }
1832 }
1833 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1834 pos += res.Unwrap();
1835 } else {
1836 return R__FORWARD_ERROR(res);
1837 }
1838
1839 std::uint32_t size = pos - base;
1840 if (auto res = SerializeEnvelopePostscript(base, size)) {
1841 size += res.Unwrap();
1842 } else {
1843 return R__FORWARD_ERROR(res);
1844 }
1845 return size;
1846}
1847
1850 void *buffer)
1851{
1852 auto base = reinterpret_cast<unsigned char *>(buffer);
1853 auto pos = base;
1854 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1855
1856 auto frame = pos;
1858 pos += SerializeUInt16(attrDesc.GetSchemaVersionMajor(), *where);
1859 pos += SerializeUInt16(attrDesc.GetSchemaVersionMinor(), *where);
1860 pos += SerializeUInt32(attrDesc.GetAnchorLength(), *where);
1861 if (auto res = SerializeLocator(attrDesc.GetAnchorLocator(), *where)) {
1862 pos += res.Unwrap();
1863 } else {
1864 return R__FORWARD_ERROR(res);
1865 }
1866 pos += SerializeString(attrDesc.GetName(), *where);
1867 auto size = pos - frame;
1868 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, size)) {
1869 return size;
1870 } else {
1871 return R__FORWARD_ERROR(res);
1872 }
1873}
1874
1875static ROOT::RResult<void> CheckFeatureFlags(const std::vector<std::uint64_t> &featureFlags)
1876{
1877 for (std::size_t i = 0; i < featureFlags.size(); ++i) {
1878 if (!featureFlags[i])
1879 continue;
1880 // NOTE: this assumes all valid feature flags are consecutive, thus we can just check the highest one set.
1881 unsigned int highestBitSet = 64 * i + (63 - ROOT::Internal::LeadingZeroes(featureFlags[i]));
1883 return R__FAIL("unsupported format feature: " + std::to_string(highestBitSet));
1884 }
1886}
1887
1890{
1891 auto base = reinterpret_cast<const unsigned char *>(buffer);
1892 auto bytes = base;
1893 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1894
1895 std::uint64_t xxhash3{0};
1896 if (auto res = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypeHeader, xxhash3)) {
1897 bytes += res.Unwrap();
1898 } else {
1899 return R__FORWARD_ERROR(res);
1900 }
1901 descBuilder.SetOnDiskHeaderXxHash3(xxhash3);
1902
1903 std::vector<std::uint64_t> featureFlags;
1904 if (auto res = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags)) {
1905 bytes += res.Unwrap();
1906 } else {
1907 return R__FORWARD_ERROR(res);
1908 }
1909 if (auto res = CheckFeatureFlags(featureFlags); !res) {
1910 return R__FORWARD_ERROR(res);
1911 }
1912
1913 std::string name;
1914 std::string description;
1915 std::string writer;
1916 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), name)) {
1917 bytes += res.Unwrap();
1918 } else {
1919 return R__FORWARD_ERROR(res);
1920 }
1921 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), description)) {
1922 bytes += res.Unwrap();
1923 } else {
1924 return R__FORWARD_ERROR(res);
1925 }
1926 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), writer)) {
1927 bytes += res.Unwrap();
1928 } else {
1929 return R__FORWARD_ERROR(res);
1930 }
1931 descBuilder.SetNTuple(name, description);
1932
1933 // Zero field
1935 .FieldId(kZeroFieldId)
1937 .MakeDescriptor()
1938 .Unwrap());
1939 if (auto res = DeserializeSchemaDescription(bytes, fnBufSizeLeft(), descBuilder)) {
1940 return RResult<void>::Success();
1941 } else {
1942 return R__FORWARD_ERROR(res);
1943 }
1944}
1945
1948{
1949 auto base = reinterpret_cast<const unsigned char *>(buffer);
1950 auto bytes = base;
1951 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1952 if (auto res = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypeFooter)) {
1953 bytes += res.Unwrap();
1954 } else {
1955 return R__FORWARD_ERROR(res);
1956 }
1957
1958 std::vector<std::uint64_t> featureFlags;
1959 if (auto res = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags)) {
1960 bytes += res.Unwrap();
1961 } else {
1962 return R__FORWARD_ERROR(res);
1963 }
1964 if (auto res = CheckFeatureFlags(featureFlags); !res) {
1965 return R__FORWARD_ERROR(res);
1966 }
1967
1968 std::uint64_t xxhash3{0};
1969 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
1970 return R__FAIL("footer too short");
1971 bytes += DeserializeUInt64(bytes, xxhash3);
1972 if (xxhash3 != descBuilder.GetDescriptor().GetOnDiskHeaderXxHash3())
1973 return R__FAIL("XxHash-3 mismatch between header and footer");
1974
1975 std::uint64_t frameSize;
1976 auto frame = bytes;
1977 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
1978
1979 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize)) {
1980 bytes += res.Unwrap();
1981 } else {
1982 return R__FORWARD_ERROR(res);
1983 }
1984 if (fnFrameSizeLeft() > 0) {
1985 descBuilder.BeginHeaderExtension();
1986 if (auto res = DeserializeSchemaDescription(bytes, fnFrameSizeLeft(), descBuilder); !res) {
1987 return R__FORWARD_ERROR(res);
1988 }
1989 }
1990 bytes = frame + frameSize;
1991
1992 {
1993 std::uint32_t nClusterGroups;
1994 frame = bytes;
1995 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nClusterGroups)) {
1996 bytes += res.Unwrap();
1997 } else {
1998 return R__FORWARD_ERROR(res);
1999 }
2000 for (std::uint32_t groupId = 0; groupId < nClusterGroups; ++groupId) {
2002 if (auto res = DeserializeClusterGroup(bytes, fnFrameSizeLeft(), clusterGroup)) {
2003 bytes += res.Unwrap();
2004 } else {
2005 return R__FORWARD_ERROR(res);
2006 }
2007
2008 descBuilder.AddToOnDiskFooterSize(clusterGroup.fPageListEnvelopeLink.fLocator.GetNBytesOnStorage());
2010 clusterGroupBuilder.ClusterGroupId(groupId)
2011 .PageListLocator(clusterGroup.fPageListEnvelopeLink.fLocator)
2012 .PageListLength(clusterGroup.fPageListEnvelopeLink.fLength)
2013 .MinEntry(clusterGroup.fMinEntry)
2014 .EntrySpan(clusterGroup.fEntrySpan)
2015 .NClusters(clusterGroup.fNClusters);
2016 descBuilder.AddClusterGroup(clusterGroupBuilder.MoveDescriptor().Unwrap());
2017 }
2018 bytes = frame + frameSize;
2019 }
2020
2021 // NOTE: Attributes were introduced in v1.0.1.0, so this section may be missing.
2022 // Testing for > 8 because bufSize includes the checksum.
2023 if (fnBufSizeLeft() > 8) {
2024 std::uint32_t nAttributeSets;
2025 frame = bytes;
2026 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nAttributeSets)) {
2027 bytes += res.Unwrap();
2028 } else {
2029 return R__FORWARD_ERROR(res);
2030 }
2031 if (nAttributeSets > 0) {
2032 R__LOG_WARNING(NTupleLog()) << "RNTuple Attributes are experimental. They are not guaranteed to be readable "
2033 "back in the future (but your main data is)";
2034 }
2035 for (std::uint32_t attrSetId = 0; attrSetId < nAttributeSets; ++attrSetId) {
2037 if (auto res = DeserializeAttributeSet(bytes, fnBufSizeLeft(), attrSetDescBld)) {
2038 descBuilder.AddAttributeSet(attrSetDescBld.MoveDescriptor().Unwrap());
2039 bytes += res.Unwrap();
2040 } else {
2041 return R__FORWARD_ERROR(res);
2042 }
2043 }
2044 bytes = frame + frameSize;
2045 }
2046
2047 return RResult<void>::Success();
2048}
2049
2052{
2053 auto base = reinterpret_cast<const unsigned char *>(buffer);
2054 auto bytes = base;
2055 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
2056
2057 std::uint64_t frameSize;
2058 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize)) {
2059 bytes += res.Unwrap();
2060 } else {
2061 return R__FORWARD_ERROR(res);
2062 }
2063 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
2064 return R__FAIL("record frame too short");
2065 std::uint16_t vMajor, vMinor;
2066 bytes += DeserializeUInt16(bytes, vMajor);
2067 bytes += DeserializeUInt16(bytes, vMinor);
2068 std::uint32_t anchorLen;
2069 bytes += DeserializeUInt32(bytes, anchorLen);
2071 if (auto res = DeserializeLocator(bytes, fnBufSizeLeft(), anchorLoc)) {
2072 bytes += res.Unwrap();
2073 } else {
2074 return R__FORWARD_ERROR(res);
2075 }
2076 std::string name;
2077 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), name)) {
2078 bytes += res.Unwrap();
2079 } else {
2080 return R__FORWARD_ERROR(res);
2081 }
2082
2083 attrSetDescBld.SchemaVersion(vMajor, vMinor).AnchorLength(anchorLen).AnchorLocator(anchorLoc).Name(name);
2084
2085 return frameSize;
2086}
2087
2091 const ROOT::RNTupleDescriptor &desc)
2092{
2093 auto base = reinterpret_cast<const unsigned char *>(buffer);
2094 auto bytes = base;
2095 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
2096
2097 if (auto res = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypePageList)) {
2098 bytes += res.Unwrap();
2099 } else {
2100 return R__FORWARD_ERROR(res);
2101 }
2102
2103 std::uint64_t xxhash3{0};
2104 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
2105 return R__FAIL("page list too short");
2106 bytes += DeserializeUInt64(bytes, xxhash3);
2107 if (xxhash3 != desc.GetOnDiskHeaderXxHash3())
2108 return R__FAIL("XxHash-3 mismatch between header and page list");
2109
2110 std::vector<RClusterDescriptorBuilder> clusterBuilders;
2112 for (ROOT::DescriptorId_t i = 0; i < clusterGroupId; ++i) {
2113 firstClusterId = firstClusterId + desc.GetClusterGroupDescriptor(i).GetNClusters();
2114 }
2115
2116 std::uint64_t clusterSummaryFrameSize;
2119
2120 std::uint32_t nClusterSummaries;
2121 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), clusterSummaryFrameSize, nClusterSummaries)) {
2122 bytes += res.Unwrap();
2123 } else {
2124 return R__FORWARD_ERROR(res);
2125 }
2128 if (auto res = DeserializeClusterSummary(bytes, fnClusterSummaryFrameSizeLeft(), clusterSummary)) {
2129 bytes += res.Unwrap();
2130 } else {
2131 return R__FORWARD_ERROR(res);
2132 }
2133
2136 clusterBuilders.emplace_back(std::move(builder));
2137 }
2139
2140 std::uint64_t topMostFrameSize;
2141 auto topMostFrame = bytes;
2142 auto fnTopMostFrameSizeLeft = [&]() { return topMostFrameSize - (bytes - topMostFrame); };
2143
2144 std::uint32_t nClusters;
2145 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), topMostFrameSize, nClusters)) {
2146 bytes += res.Unwrap();
2147 } else {
2148 return R__FORWARD_ERROR(res);
2149 }
2150
2152 return R__FAIL("mismatch between number of clusters and number of cluster summaries");
2153
2154 for (std::uint32_t i = 0; i < nClusters; ++i) {
2155 std::uint64_t outerFrameSize;
2156 auto outerFrame = bytes;
2157 auto fnOuterFrameSizeLeft = [&]() { return outerFrameSize - (bytes - outerFrame); };
2158
2159 std::uint32_t nColumns;
2160 if (auto res = DeserializeFrameHeader(bytes, fnTopMostFrameSizeLeft(), outerFrameSize, nColumns)) {
2161 bytes += res.Unwrap();
2162 } else {
2163 return R__FORWARD_ERROR(res);
2164 }
2165
2166 for (std::uint32_t j = 0; j < nColumns; ++j) {
2167 std::uint64_t innerFrameSize;
2168 auto innerFrame = bytes;
2169 auto fnInnerFrameSizeLeft = [&]() { return innerFrameSize - (bytes - innerFrame); };
2170
2171 std::uint32_t nPages;
2172 if (auto res = DeserializeFrameHeader(bytes, fnOuterFrameSizeLeft(), innerFrameSize, nPages)) {
2173 bytes += res.Unwrap();
2174 } else {
2175 return R__FORWARD_ERROR(res);
2176 }
2177
2179 pageRange.SetPhysicalColumnId(j);
2180 for (std::uint32_t k = 0; k < nPages; ++k) {
2181 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
2182 return R__FAIL("inner frame too short");
2183 std::int32_t nElements;
2184 bool hasChecksum = false;
2186 bytes += DeserializeInt32(bytes, nElements);
2187 if (nElements < 0) {
2189 hasChecksum = true;
2190 }
2191 if (auto res = DeserializeLocator(bytes, fnInnerFrameSizeLeft(), locator)) {
2192 bytes += res.Unwrap();
2193 } else {
2194 return R__FORWARD_ERROR(res);
2195 }
2196 pageRange.GetPageInfos().push_back({static_cast<std::uint32_t>(nElements), locator, hasChecksum});
2197 }
2198
2199 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::int64_t)))
2200 return R__FAIL("page list frame too short");
2201 std::int64_t columnOffset;
2202 bytes += DeserializeInt64(bytes, columnOffset);
2203 if (columnOffset < 0) {
2204 if (nPages > 0)
2205 return R__FAIL("unexpected non-empty page list");
2206 clusterBuilders[i].MarkSuppressedColumnRange(j);
2207 } else {
2208 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
2209 return R__FAIL("page list frame too short");
2210 std::uint32_t compressionSettings;
2211 bytes += DeserializeUInt32(bytes, compressionSettings);
2213 }
2214
2216 } // loop over columns
2217
2219 } // loop over clusters
2220
2221 return clusterBuilders;
2222}
2223
2228{
2230 if (!clusterBuildersRes)
2232
2233 auto clusterBuilders = clusterBuildersRes.Unwrap();
2234
2235 std::vector<ROOT::RClusterDescriptor> clusters;
2236 clusters.reserve(clusterBuilders.size());
2237
2238 // Conditionally fixup the clusters depending on the attach purpose
2239 switch (mode) {
2240 case EDescriptorDeserializeMode::kForReading:
2241 for (auto &builder : clusterBuilders) {
2242 if (auto res = builder.CommitSuppressedColumnRanges(desc); !res)
2243 return R__FORWARD_RESULT(res);
2244 builder.AddExtendedColumnRanges(desc);
2245 clusters.emplace_back(builder.MoveDescriptor().Unwrap());
2246 }
2247 break;
2248 case EDescriptorDeserializeMode::kForWriting:
2249 for (auto &builder : clusterBuilders) {
2250 if (auto res = builder.CommitSuppressedColumnRanges(desc); !res)
2251 return R__FORWARD_RESULT(res);
2252 clusters.emplace_back(builder.MoveDescriptor().Unwrap());
2253 }
2254 break;
2255 case EDescriptorDeserializeMode::kRaw:
2256 for (auto &builder : clusterBuilders)
2257 clusters.emplace_back(builder.MoveDescriptor().Unwrap());
2258 break;
2259 }
2260
2262
2263 return RResult<void>::Success();
2264}
2265
2267{
2269 for (auto si : infos) {
2270 assert(si.first == si.second->GetNumber());
2271 streamerInfos.Add(si.second);
2272 }
2274 buffer.WriteObject(&streamerInfos);
2275 assert(buffer.Length() > 0);
2276 return std::string{buffer.Buffer(), static_cast<UInt_t>(buffer.Length())};
2277}
2278
2281{
2283
2284 TBufferFile buffer(TBuffer::kRead, extraTypeInfoContent.length(), const_cast<char *>(extraTypeInfoContent.data()),
2285 false /* adopt */);
2286 auto infoList = reinterpret_cast<TList *>(buffer.ReadObject(TList::Class()));
2287
2288 TObjLink *lnk = infoList->FirstLink();
2289 while (lnk) {
2290 auto info = reinterpret_cast<TStreamerInfo *>(lnk->GetObject());
2291 info->BuildCheck();
2292 infoMap[info->GetNumber()] = info->GetClass()->GetStreamerInfo(info->GetClassVersion());
2293 assert(info->GetNumber() == infoMap[info->GetNumber()]->GetNumber());
2294 lnk = lnk->Next();
2295 }
2296
2297 delete infoList;
2298
2299 return infoMap;
2300}
#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
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#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
The available trivial, native content types of a column.
Metadata stored for every Attribute Set linked to an RNTuple.
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.
A helper class for piece-wise construction of an RColumnDescriptor.
A helper class for piece-wise construction of an RExtraTypeInfoDescriptor.
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.
A helper class for piece-wise construction of an RNTupleDescriptor.
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 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,...
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 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 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 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 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)
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.
Metadata stored for every column of an RNTuple.
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.
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
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 that is common for object stores using 64bit location information.
Generic information about the physical location of data.
void SetType(ELocatorType type)
const_iterator begin() const
const_iterator end() const
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()
Describes a persistent version of a class.
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:51
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