Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
RNTupleSerialize.cxx
Go to the documentation of this file.
1/// \file RNTupleSerialize.cxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \author Javier Lopez-Gomez <javier.lopez.gomez@cern.ch>
5/// \date 2021-08-02
6/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
7/// is welcome!
8
9/*************************************************************************
10 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
11 * All rights reserved. *
12 * *
13 * For the licensing terms see $ROOTSYS/LICENSE. *
14 * For the list of contributors see $ROOTSYS/README/CREDITS. *
15 *************************************************************************/
16
18#include <ROOT/RError.hxx>
21#include <ROOT/RNTupleUtil.hxx>
22
23#include <RVersion.h>
24#include <TBufferFile.h>
25#include <TClass.h>
26#include <TList.h>
27#include <TStreamerInfo.h>
29#include <xxhash.h>
30
31#include <cassert>
32#include <cmath>
33#include <cstring> // for memcpy
34#include <deque>
35#include <functional>
36#include <limits>
37#include <set>
38#include <unordered_map>
39
46
47namespace {
49
53{
54
55 auto base = reinterpret_cast<unsigned char *>(buffer);
56 auto pos = base;
57 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
58
59 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
60
61 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetFieldVersion(), *where);
62 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetTypeVersion(), *where);
63 pos += RNTupleSerializer::SerializeUInt32(onDiskParentId, *where);
64 if (auto res = RNTupleSerializer::SerializeFieldStructure(fieldDesc.GetStructure(), *where)) {
65 pos += res.Unwrap();
66 } else {
67 return R__FORWARD_ERROR(res);
68 }
69
70 std::uint16_t flags = 0;
71 if (fieldDesc.GetNRepetitions() > 0)
72 flags |= RNTupleSerializer::kFlagRepetitiveField;
73 if (fieldDesc.IsProjectedField())
74 flags |= RNTupleSerializer::kFlagProjectedField;
75 if (fieldDesc.GetTypeChecksum().has_value())
76 flags |= RNTupleSerializer::kFlagHasTypeChecksum;
77 pos += RNTupleSerializer::SerializeUInt16(flags, *where);
78
79 pos += RNTupleSerializer::SerializeString(fieldDesc.GetFieldName(), *where);
80 pos += RNTupleSerializer::SerializeString(fieldDesc.GetTypeName(), *where);
81 pos += RNTupleSerializer::SerializeString(fieldDesc.GetTypeAlias(), *where);
82 pos += RNTupleSerializer::SerializeString(fieldDesc.GetFieldDescription(), *where);
83
84 if (flags & RNTupleSerializer::kFlagRepetitiveField) {
85 pos += RNTupleSerializer::SerializeUInt64(fieldDesc.GetNRepetitions(), *where);
86 }
87 if (flags & RNTupleSerializer::kFlagProjectedField) {
88 pos += RNTupleSerializer::SerializeUInt32(onDiskProjectionSourceId, *where);
89 }
90 if (flags & RNTupleSerializer::kFlagHasTypeChecksum) {
91 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetTypeChecksum().value(), *where);
92 }
93
94 auto size = pos - base;
95 RNTupleSerializer::SerializeFramePostscript(base, size);
96
97 return size;
98}
99
100// clang-format off
101/// Serialize, in order, fields enumerated in `fieldList` to `buffer`. `firstOnDiskId` specifies the on-disk ID for the
102/// first element in the `fieldList` sequence. Before calling this function `RContext::MapSchema()` should have been
103/// called on `context` in order to map in-memory field IDs to their on-disk counterpart.
104/// \return The number of bytes written to the output buffer; if `buffer` is `nullptr` no data is serialized and the
105/// required buffer size is returned
106// clang-format on
108SerializeFieldList(const ROOT::RNTupleDescriptor &desc, std::span<const ROOT::DescriptorId_t> fieldList,
110 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::kLeaf};
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 return frameSize;
227}
228
232{
233 R__ASSERT(!columnDesc.IsAliasColumn());
234
235 auto base = reinterpret_cast<unsigned char *>(buffer);
236 auto pos = base;
237 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
238
239 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
240
241 if (auto res = RNTupleSerializer::SerializeColumnType(columnDesc.GetType(), *where)) {
242 pos += res.Unwrap();
243 } else {
244 return R__FORWARD_ERROR(res);
245 }
246 pos += RNTupleSerializer::SerializeUInt16(columnDesc.GetBitsOnStorage(), *where);
247 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskFieldId(columnDesc.GetFieldId()), *where);
248 std::uint16_t flags = 0;
249 if (columnDesc.IsDeferredColumn())
250 flags |= RNTupleSerializer::kFlagDeferredColumn;
251 if (columnDesc.GetValueRange().has_value())
252 flags |= RNTupleSerializer::kFlagHasValueRange;
253 std::int64_t firstElementIdx = columnDesc.GetFirstElementIndex();
254 if (columnDesc.IsSuppressedDeferredColumn())
256 pos += RNTupleSerializer::SerializeUInt16(flags, *where);
257 pos += RNTupleSerializer::SerializeUInt16(columnDesc.GetRepresentationIndex(), *where);
258 if (flags & RNTupleSerializer::kFlagDeferredColumn)
259 pos += RNTupleSerializer::SerializeInt64(firstElementIdx, *where);
260 if (flags & RNTupleSerializer::kFlagHasValueRange) {
261 auto [min, max] = *columnDesc.GetValueRange();
262 std::uint64_t intMin, intMax;
263 static_assert(sizeof(min) == sizeof(intMin) && sizeof(max) == sizeof(intMax));
264 memcpy(&intMin, &min, sizeof(min));
265 memcpy(&intMax, &max, sizeof(max));
266 pos += RNTupleSerializer::SerializeUInt64(intMin, *where);
267 pos += RNTupleSerializer::SerializeUInt64(intMax, *where);
268 }
269
270 if (auto res = RNTupleSerializer::SerializeFramePostscript(buffer ? base : nullptr, pos - base)) {
271 pos += res.Unwrap();
272 } else {
273 return R__FORWARD_ERROR(res);
274 }
275
276 return pos - base;
277}
278
280SerializeColumnsOfFields(const ROOT::RNTupleDescriptor &desc, std::span<const ROOT::DescriptorId_t> fieldList,
283{
284 auto base = reinterpret_cast<unsigned char *>(buffer);
285 auto pos = base;
286 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
287
288 const auto *xHeader = !forHeaderExtension ? desc.GetHeaderExtension() : nullptr;
289
290 for (auto parentId : fieldList) {
291 // If we're serializing the non-extended header and we already have a header extension (which may happen if
292 // we load an RNTuple for incremental merging), we need to skip all the extended fields, as they need to be
293 // written in the header extension, not in the regular header.
294 if (xHeader && xHeader->ContainsField(parentId))
295 continue;
296
297 for (const auto &c : desc.GetColumnIterable(parentId)) {
298 if (c.IsAliasColumn() || (xHeader && xHeader->ContainsExtendedColumnRepresentation(c.GetLogicalId())))
299 continue;
300
301 if (auto res = SerializePhysicalColumn(c, context, *where)) {
302 pos += res.Unwrap();
303 } else {
304 return R__FORWARD_ERROR(res);
305 }
306 }
307 }
308
309 return pos - base;
310}
311
314{
316
317 auto base = reinterpret_cast<const unsigned char *>(buffer);
318 auto bytes = base;
319 std::uint64_t frameSize;
320 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
321 if (auto res = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize)) {
322 bytes += res.Unwrap();
323 } else {
324 return R__FORWARD_ERROR(res);
325 }
326
327 // Initialize properly for SerializeColumnType
328 ENTupleColumnType type{ENTupleColumnType::kIndex32};
329 std::uint16_t bitsOnStorage;
330 std::uint32_t fieldId;
331 std::uint16_t flags;
332 std::uint16_t representationIndex;
333 std::int64_t firstElementIdx = 0;
334 if (fnFrameSizeLeft() < RNTupleSerializer::SerializeColumnType(type, nullptr).Unwrap() + sizeof(std::uint16_t) +
335 2 * sizeof(std::uint32_t)) {
336 return R__FAIL("column record frame too short");
337 }
338 if (auto res = RNTupleSerializer::DeserializeColumnType(bytes, type)) {
339 bytes += res.Unwrap();
340 } else {
341 return R__FORWARD_ERROR(res);
342 }
343 bytes += RNTupleSerializer::DeserializeUInt16(bytes, bitsOnStorage);
344 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldId);
345 bytes += RNTupleSerializer::DeserializeUInt16(bytes, flags);
346 bytes += RNTupleSerializer::DeserializeUInt16(bytes, representationIndex);
347 if (flags & RNTupleSerializer::kFlagDeferredColumn) {
348 if (fnFrameSizeLeft() < sizeof(std::uint64_t))
349 return R__FAIL("column record frame too short");
350 bytes += RNTupleSerializer::DeserializeInt64(bytes, firstElementIdx);
351 }
352 if (flags & RNTupleSerializer::kFlagHasValueRange) {
353 if (fnFrameSizeLeft() < 2 * sizeof(std::uint64_t))
354 return R__FAIL("field record frame too short");
355 std::uint64_t minInt, maxInt;
356 bytes += RNTupleSerializer::DeserializeUInt64(bytes, minInt);
357 bytes += RNTupleSerializer::DeserializeUInt64(bytes, maxInt);
358 double min, max;
359 memcpy(&min, &minInt, sizeof(min));
360 memcpy(&max, &maxInt, sizeof(max));
361 columnDesc.ValueRange(min, max);
362 }
363
364 columnDesc.FieldId(fieldId).BitsOnStorage(bitsOnStorage).Type(type).RepresentationIndex(representationIndex);
365 columnDesc.FirstElementIndex(std::abs(firstElementIdx));
366 if (firstElementIdx < 0)
367 columnDesc.SetSuppressedDeferred();
368
369 return frameSize;
370}
371
373{
374 auto base = reinterpret_cast<unsigned char *>(buffer);
375 auto pos = base;
376 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
377
378 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
379
380 if (auto res = RNTupleSerializer::SerializeExtraTypeInfoId(desc.GetContentId(), *where)) {
381 pos += res.Unwrap();
382 } else {
383 return R__FORWARD_ERROR(res);
384 }
385 pos += RNTupleSerializer::SerializeUInt32(desc.GetTypeVersion(), *where);
386 pos += RNTupleSerializer::SerializeString(desc.GetTypeName(), *where);
387 pos += RNTupleSerializer::SerializeString(desc.GetContent(), *where);
388
389 auto size = pos - base;
390 RNTupleSerializer::SerializeFramePostscript(base, size);
391
392 return size;
393}
394
396{
397 auto base = reinterpret_cast<unsigned char *>(buffer);
398 auto pos = base;
399 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
400
401 for (const auto &extraTypeInfoDesc : ntplDesc.GetExtraTypeInfoIterable()) {
403 pos += res.Unwrap();
404 } else {
405 return R__FORWARD_ERROR(res);
406 }
407 }
408
409 return pos - base;
410}
411
412ROOT::RResult<std::uint32_t> DeserializeExtraTypeInfo(const void *buffer, std::uint64_t bufSize,
414{
416
417 auto base = reinterpret_cast<const unsigned char *>(buffer);
418 auto bytes = base;
419 std::uint64_t frameSize;
420 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
421 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
422 if (!result)
423 return R__FORWARD_ERROR(result);
424 bytes += result.Unwrap();
425
426 EExtraTypeInfoIds contentId{EExtraTypeInfoIds::kInvalid};
427 std::uint32_t typeVersion;
428 if (fnFrameSizeLeft() < 2 * sizeof(std::uint32_t)) {
429 return R__FAIL("extra type info record frame too short");
430 }
431 result = RNTupleSerializer::DeserializeExtraTypeInfoId(bytes, contentId);
432 if (!result)
433 return R__FORWARD_ERROR(result);
434 bytes += result.Unwrap();
435 bytes += RNTupleSerializer::DeserializeUInt32(bytes, typeVersion);
436
437 std::string typeName;
438 std::string content;
439 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), typeName).Unwrap();
440 if (!result)
441 return R__FORWARD_ERROR(result);
442 bytes += result.Unwrap();
443 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), content).Unwrap();
444 if (!result)
445 return R__FORWARD_ERROR(result);
446 bytes += result.Unwrap();
447
449
450 return frameSize;
451}
452
453std::uint32_t SerializeLocatorPayloadLarge(const ROOT::RNTupleLocator &locator, unsigned char *buffer)
454{
455 if (buffer) {
456 RNTupleSerializer::SerializeUInt64(locator.GetNBytesOnStorage(), buffer);
457 RNTupleSerializer::SerializeUInt64(locator.GetPosition<std::uint64_t>(), buffer + sizeof(std::uint64_t));
458 }
459 return sizeof(std::uint64_t) + sizeof(std::uint64_t);
460}
461
462void DeserializeLocatorPayloadLarge(const unsigned char *buffer, ROOT::RNTupleLocator &locator)
463{
464 std::uint64_t nBytesOnStorage;
465 std::uint64_t position;
466 RNTupleSerializer::DeserializeUInt64(buffer, nBytesOnStorage);
467 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint64_t), position);
468 locator.SetNBytesOnStorage(nBytesOnStorage);
469 locator.SetPosition(position);
470}
471
472std::uint32_t SerializeLocatorPayloadObject64(const ROOT::RNTupleLocator &locator, unsigned char *buffer)
473{
474 const auto &data = locator.GetPosition<ROOT::RNTupleLocatorObject64>();
475 const uint32_t sizeofNBytesOnStorage = (locator.GetNBytesOnStorage() > std::numeric_limits<std::uint32_t>::max())
476 ? sizeof(std::uint64_t)
477 : sizeof(std::uint32_t);
478 if (buffer) {
479 if (sizeofNBytesOnStorage == sizeof(std::uint32_t)) {
480 RNTupleSerializer::SerializeUInt32(locator.GetNBytesOnStorage(), buffer);
481 } else {
482 RNTupleSerializer::SerializeUInt64(locator.GetNBytesOnStorage(), buffer);
483 }
484 RNTupleSerializer::SerializeUInt64(data.GetLocation(), buffer + sizeofNBytesOnStorage);
485 }
486 return sizeofNBytesOnStorage + sizeof(std::uint64_t);
487}
488
489ROOT::RResult<void> DeserializeLocatorPayloadObject64(const unsigned char *buffer, std::uint32_t sizeofLocatorPayload,
491{
492 std::uint64_t location;
493 if (sizeofLocatorPayload == 12) {
494 std::uint32_t nBytesOnStorage;
495 RNTupleSerializer::DeserializeUInt32(buffer, nBytesOnStorage);
496 locator.SetNBytesOnStorage(nBytesOnStorage);
497 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint32_t), location);
498 } else if (sizeofLocatorPayload == 16) {
499 std::uint64_t nBytesOnStorage;
500 RNTupleSerializer::DeserializeUInt64(buffer, nBytesOnStorage);
501 locator.SetNBytesOnStorage(nBytesOnStorage);
502 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint64_t), location);
503 } else {
504 return R__FAIL("invalid DAOS locator payload size: " + std::to_string(sizeofLocatorPayload));
505 }
506 locator.SetPosition(ROOT::RNTupleLocatorObject64{location});
508}
509
512 void *buffer)
513{
514 R__ASSERT(columnDesc.IsAliasColumn());
515
516 auto base = reinterpret_cast<unsigned char *>(buffer);
517 auto pos = base;
518 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
519
520 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
521
522 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskColumnId(columnDesc.GetPhysicalId()), *where);
523 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskFieldId(columnDesc.GetFieldId()), *where);
524
525 pos += RNTupleSerializer::SerializeFramePostscript(buffer ? base : nullptr, pos - base).Unwrap();
526
527 return pos - base;
528}
529
531 std::span<const ROOT::DescriptorId_t> fieldList,
533 void *buffer, bool forHeaderExtension)
534{
535 auto base = reinterpret_cast<unsigned char *>(buffer);
536 auto pos = base;
537 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
538
539 const auto *xHeader = !forHeaderExtension ? desc.GetHeaderExtension() : nullptr;
540
541 for (auto parentId : fieldList) {
542 if (xHeader && xHeader->ContainsField(parentId))
543 continue;
544
545 for (const auto &c : desc.GetColumnIterable(parentId)) {
546 if (!c.IsAliasColumn() || (xHeader && xHeader->ContainsExtendedColumnRepresentation(c.GetLogicalId())))
547 continue;
548
549 pos += SerializeAliasColumn(c, context, *where);
550 }
551 }
552
553 return pos - base;
554}
555
556ROOT::RResult<std::uint32_t> DeserializeAliasColumn(const void *buffer, std::uint64_t bufSize,
557 std::uint32_t &physicalColumnId, std::uint32_t &fieldId)
558{
559 auto base = reinterpret_cast<const unsigned char *>(buffer);
560 auto bytes = base;
561 std::uint64_t frameSize;
562 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
563 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
564 if (!result)
565 return R__FORWARD_ERROR(result);
566 bytes += result.Unwrap();
567
568 if (fnFrameSizeLeft() < 2 * sizeof(std::uint32_t)) {
569 return R__FAIL("alias column record frame too short");
570 }
571
572 bytes += RNTupleSerializer::DeserializeUInt32(bytes, physicalColumnId);
573 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldId);
574
575 return frameSize;
576}
577
578} // anonymous namespace
579
581 std::uint64_t length,
582 std::uint64_t &xxhash3, void *buffer)
583{
584 if (buffer != nullptr) {
586 SerializeUInt64(xxhash3, buffer);
587 }
588 return 8;
589}
590
592 std::uint64_t length,
593 std::uint64_t &xxhash3)
594{
596 DeserializeUInt64(data + length, xxhash3);
597 if (xxhash3 != checksumReal)
598 return R__FAIL("XxHash-3 checksum mismatch");
599 return RResult<void>::Success();
600}
601
604{
605 std::uint64_t xxhash3;
606 return R__FORWARD_RESULT(VerifyXxHash3(data, length, xxhash3));
607}
608
609std::uint32_t ROOT::Experimental::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::Experimental::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::Experimental::Internal::RNTupleSerializer::SerializeUInt16(std::uint16_t val, void *buffer)
627{
628 return SerializeInt16(val, buffer);
629}
630
631std::uint32_t ROOT::Experimental::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::Experimental::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::Experimental::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::Experimental::Internal::RNTupleSerializer::SerializeUInt32(std::uint32_t val, void *buffer)
657{
658 return SerializeInt32(val, buffer);
659}
660
661std::uint32_t ROOT::Experimental::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::Experimental::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::Experimental::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::Experimental::Internal::RNTupleSerializer::SerializeUInt64(std::uint64_t val, void *buffer)
692{
693 return SerializeInt64(val, buffer);
694}
695
696std::uint32_t ROOT::Experimental::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::Experimental::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
712 std::uint64_t bufSize,
713 std::string &val)
714{
715 if (bufSize < sizeof(std::uint32_t))
716 return R__FAIL("string buffer too short");
717 bufSize -= sizeof(std::uint32_t);
718
719 auto base = reinterpret_cast<const unsigned char *>(buffer);
720 auto bytes = base;
721 std::uint32_t length;
722 bytes += DeserializeUInt32(buffer, length);
723 if (bufSize < length)
724 return R__FAIL("string buffer too short");
725
726 val.resize(length);
727 memcpy(&val[0], bytes, length);
728 return sizeof(std::uint32_t) + length;
729}
730
733{
734 switch (type) {
735 case ENTupleColumnType::kBit: return SerializeUInt16(0x00, buffer);
736 case ENTupleColumnType::kByte: return SerializeUInt16(0x01, buffer);
737 case ENTupleColumnType::kChar: return SerializeUInt16(0x02, buffer);
738 case ENTupleColumnType::kInt8: return SerializeUInt16(0x03, buffer);
739 case ENTupleColumnType::kUInt8: return SerializeUInt16(0x04, buffer);
740 case ENTupleColumnType::kInt16: return SerializeUInt16(0x05, buffer);
741 case ENTupleColumnType::kUInt16: return SerializeUInt16(0x06, buffer);
742 case ENTupleColumnType::kInt32: return SerializeUInt16(0x07, buffer);
743 case ENTupleColumnType::kUInt32: return SerializeUInt16(0x08, buffer);
744 case ENTupleColumnType::kInt64: return SerializeUInt16(0x09, buffer);
745 case ENTupleColumnType::kUInt64: return SerializeUInt16(0x0A, buffer);
746 case ENTupleColumnType::kReal16: return SerializeUInt16(0x0B, buffer);
747 case ENTupleColumnType::kReal32: return SerializeUInt16(0x0C, buffer);
748 case ENTupleColumnType::kReal64: return SerializeUInt16(0x0D, buffer);
749 case ENTupleColumnType::kIndex32: return SerializeUInt16(0x0E, buffer);
750 case ENTupleColumnType::kIndex64: return SerializeUInt16(0x0F, buffer);
751 case ENTupleColumnType::kSwitch: return SerializeUInt16(0x10, buffer);
752 case ENTupleColumnType::kSplitInt16: return SerializeUInt16(0x11, buffer);
753 case ENTupleColumnType::kSplitUInt16: return SerializeUInt16(0x12, buffer);
754 case ENTupleColumnType::kSplitInt32: return SerializeUInt16(0x13, buffer);
755 case ENTupleColumnType::kSplitUInt32: return SerializeUInt16(0x14, buffer);
756 case ENTupleColumnType::kSplitInt64: return SerializeUInt16(0x15, buffer);
757 case ENTupleColumnType::kSplitUInt64: return SerializeUInt16(0x16, buffer);
758 case ENTupleColumnType::kSplitReal32: return SerializeUInt16(0x18, buffer);
759 case ENTupleColumnType::kSplitReal64: return SerializeUInt16(0x19, buffer);
760 case ENTupleColumnType::kSplitIndex32: return SerializeUInt16(0x1A, buffer);
761 case ENTupleColumnType::kSplitIndex64: return SerializeUInt16(0x1B, buffer);
762 case ENTupleColumnType::kReal32Trunc: return SerializeUInt16(0x1C, buffer);
763 case ENTupleColumnType::kReal32Quant: return SerializeUInt16(0x1D, buffer);
764 default:
766 return SerializeUInt16(0x99, buffer);
767 return R__FAIL("unexpected column type");
768 }
769}
770
773{
774 std::uint16_t onDiskType;
775 auto result = DeserializeUInt16(buffer, onDiskType);
776
777 switch (onDiskType) {
778 case 0x00: type = ENTupleColumnType::kBit; break;
779 case 0x01: type = ENTupleColumnType::kByte; break;
780 case 0x02: type = ENTupleColumnType::kChar; break;
781 case 0x03: type = ENTupleColumnType::kInt8; break;
782 case 0x04: type = ENTupleColumnType::kUInt8; break;
783 case 0x05: type = ENTupleColumnType::kInt16; break;
784 case 0x06: type = ENTupleColumnType::kUInt16; break;
785 case 0x07: type = ENTupleColumnType::kInt32; break;
786 case 0x08: type = ENTupleColumnType::kUInt32; break;
787 case 0x09: type = ENTupleColumnType::kInt64; break;
788 case 0x0A: type = ENTupleColumnType::kUInt64; break;
789 case 0x0B: type = ENTupleColumnType::kReal16; break;
790 case 0x0C: type = ENTupleColumnType::kReal32; break;
791 case 0x0D: type = ENTupleColumnType::kReal64; break;
792 case 0x0E: type = ENTupleColumnType::kIndex32; break;
793 case 0x0F: type = ENTupleColumnType::kIndex64; break;
794 case 0x10: type = ENTupleColumnType::kSwitch; break;
795 case 0x11: type = ENTupleColumnType::kSplitInt16; break;
796 case 0x12: type = ENTupleColumnType::kSplitUInt16; break;
797 case 0x13: type = ENTupleColumnType::kSplitInt32; break;
798 case 0x14: type = ENTupleColumnType::kSplitUInt32; break;
799 case 0x15: type = ENTupleColumnType::kSplitInt64; break;
800 case 0x16: type = ENTupleColumnType::kSplitUInt64; break;
801 case 0x18: type = ENTupleColumnType::kSplitReal32; break;
802 case 0x19: type = ENTupleColumnType::kSplitReal64; break;
803 case 0x1A: type = ENTupleColumnType::kSplitIndex32; break;
804 case 0x1B: type = ENTupleColumnType::kSplitIndex64; break;
805 case 0x1C: type = ENTupleColumnType::kReal32Trunc; break;
806 case 0x1D: type = ENTupleColumnType::kReal32Quant; break;
807 // case 0x99 => kTestFutureColumnType missing on purpose
808 default:
809 // may be a column type introduced by a future version
811 break;
812 }
813 return result;
814}
815
818{
819 using ENTupleStructure = ROOT::ENTupleStructure;
820 switch (structure) {
821 case ENTupleStructure::kLeaf: return SerializeUInt16(0x00, buffer);
822 case ENTupleStructure::kCollection: return SerializeUInt16(0x01, buffer);
823 case ENTupleStructure::kRecord: return SerializeUInt16(0x02, buffer);
824 case ENTupleStructure::kVariant: return SerializeUInt16(0x03, buffer);
825 case ENTupleStructure::kStreamer: return SerializeUInt16(0x04, buffer);
826 default:
828 return SerializeUInt16(0x99, buffer);
829 return R__FAIL("unexpected field structure type");
830 }
831}
832
835 ROOT::ENTupleStructure &structure)
836{
837 using ENTupleStructure = ROOT::ENTupleStructure;
838 std::uint16_t onDiskValue;
839 auto result = DeserializeUInt16(buffer, onDiskValue);
840 switch (onDiskValue) {
841 case 0x00: structure = ENTupleStructure::kLeaf; break;
842 case 0x01: structure = ENTupleStructure::kCollection; break;
843 case 0x02: structure = ENTupleStructure::kRecord; break;
844 case 0x03: structure = ENTupleStructure::kVariant; break;
845 case 0x04: structure = ENTupleStructure::kStreamer; break;
846 // case 0x99 => kTestFutureFieldStructure intentionally missing
847 default: structure = ENTupleStructure::kUnknown;
848 }
849 return result;
850}
851
854{
855 switch (id) {
856 case ROOT::EExtraTypeInfoIds::kStreamerInfo: return SerializeUInt32(0x00, buffer);
857 default: return R__FAIL("unexpected extra type info id");
858 }
859}
860
864{
865 std::uint32_t onDiskValue;
866 auto result = DeserializeUInt32(buffer, onDiskValue);
867 switch (onDiskValue) {
868 case 0x00: id = ROOT::EExtraTypeInfoIds::kStreamerInfo; break;
869 default:
871 R__LOG_DEBUG(0, ROOT::Internal::NTupleLog()) << "Unknown extra type info id: " << onDiskValue;
872 }
873 return result;
874}
875
876std::uint32_t
878{
879 auto base = reinterpret_cast<unsigned char *>(buffer);
880 auto pos = base;
881 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
882
883 pos += SerializeUInt64(envelopeType, *where);
884 // The 48bits size information is filled in the postscript
885 return pos - base;
886}
887
890 std::uint64_t size, std::uint64_t &xxhash3)
891{
892 if (size < sizeof(std::uint64_t))
893 return R__FAIL("envelope size too small");
894 if (size >= static_cast<uint64_t>(1) << 48)
895 return R__FAIL("envelope size too big");
896 if (envelope) {
897 std::uint64_t typeAndSize;
898 DeserializeUInt64(envelope, typeAndSize);
899 typeAndSize |= (size + 8) << 16;
900 SerializeUInt64(typeAndSize, envelope);
901 }
902 return SerializeXxHash3(envelope, size, xxhash3, envelope ? (envelope + size) : nullptr);
903}
904
907 std::uint64_t size)
908{
909 std::uint64_t xxhash3;
910 return R__FORWARD_RESULT(SerializeEnvelopePostscript(envelope, size, xxhash3));
911}
912
915 std::uint16_t expectedType, std::uint64_t &xxhash3)
916{
917 const std::uint64_t minEnvelopeSize = sizeof(std::uint64_t) + sizeof(std::uint64_t);
919 return R__FAIL("invalid envelope buffer, too short");
920
921 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
922 auto base = bytes;
923
924 std::uint64_t typeAndSize;
925 bytes += DeserializeUInt64(bytes, typeAndSize);
926
927 std::uint16_t envelopeType = typeAndSize & 0xFFFF;
928 if (envelopeType != expectedType) {
929 return R__FAIL("envelope type mismatch: expected " + std::to_string(expectedType) + ", found " +
930 std::to_string(envelopeType));
931 }
932
933 std::uint64_t envelopeSize = typeAndSize >> 16;
934 if (bufSize < envelopeSize)
935 return R__FAIL("envelope buffer size too small");
937 return R__FAIL("invalid envelope, too short");
938
939 auto result = VerifyXxHash3(base, envelopeSize - 8, xxhash3);
940 if (!result)
941 return R__FORWARD_ERROR(result);
942
943 return sizeof(typeAndSize);
944}
945
948 std::uint16_t expectedType)
949{
950 std::uint64_t xxhash3;
951 return R__FORWARD_RESULT(DeserializeEnvelope(buffer, bufSize, expectedType, xxhash3));
952}
953
955{
956 // Marker: multiply the final size with 1
957 return SerializeInt64(1, buffer);
958}
959
960std::uint32_t
962{
963 auto base = reinterpret_cast<unsigned char *>(buffer);
964 auto pos = base;
965 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
966
967 // Marker: multiply the final size with -1
968 pos += SerializeInt64(-1, *where);
969 pos += SerializeUInt32(nitems, *where);
970 return pos - base;
971}
972
975{
976 auto preambleSize = sizeof(std::int64_t);
977 if (size < preambleSize)
978 return R__FAIL("frame too short: " + std::to_string(size));
979 if (frame) {
980 std::int64_t marker;
981 DeserializeInt64(frame, marker);
982 if ((marker < 0) && (size < (sizeof(std::uint32_t) + preambleSize)))
983 return R__FAIL("frame too short: " + std::to_string(size));
984 SerializeInt64(marker * static_cast<int64_t>(size), frame);
985 }
986 return 0;
987}
988
991 std::uint64_t &frameSize, std::uint32_t &nitems)
992{
993 std::uint64_t minSize = sizeof(std::int64_t);
994 if (bufSize < minSize)
995 return R__FAIL("frame too short");
996
997 std::int64_t *ssize = reinterpret_cast<std::int64_t *>(&frameSize);
998 DeserializeInt64(buffer, *ssize);
999
1000 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1001 bytes += minSize;
1002
1003 if (*ssize >= 0) {
1004 // Record frame
1005 nitems = 1;
1006 } else {
1007 // List frame
1008 minSize += sizeof(std::uint32_t);
1009 if (bufSize < minSize)
1010 return R__FAIL("frame too short");
1011 bytes += DeserializeUInt32(bytes, nitems);
1012 *ssize = -(*ssize);
1013 }
1014
1015 if (frameSize < minSize)
1016 return R__FAIL("corrupt frame size");
1017 if (bufSize < frameSize)
1018 return R__FAIL("frame too short");
1019
1020 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1021}
1022
1025 std::uint64_t &frameSize)
1026{
1027 std::uint32_t nitems;
1028 return R__FORWARD_RESULT(DeserializeFrameHeader(buffer, bufSize, frameSize, nitems));
1029}
1030
1033 void *buffer)
1034{
1035 if (flags.empty())
1036 return SerializeUInt64(0, buffer);
1037
1038 if (buffer) {
1039 auto bytes = reinterpret_cast<unsigned char *>(buffer);
1040
1041 for (unsigned i = 0; i < flags.size(); ++i) {
1042 if (flags[i] & 0x8000000000000000)
1043 return R__FAIL("feature flag out of bounds");
1044
1045 // The MSb indicates that another Int64 follows; set this bit to 1 for all except the last element
1046 if (i == (flags.size() - 1))
1047 SerializeUInt64(flags[i], bytes);
1048 else
1049 bytes += SerializeUInt64(flags[i] | 0x8000000000000000, bytes);
1050 }
1051 }
1052 return (flags.size() * sizeof(std::int64_t));
1053}
1054
1057 std::vector<std::uint64_t> &flags)
1058{
1059 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1060
1061 flags.clear();
1062 std::uint64_t f;
1063 do {
1064 if (bufSize < sizeof(std::uint64_t))
1065 return R__FAIL("feature flag buffer too short");
1066 bytes += DeserializeUInt64(bytes, f);
1067 bufSize -= sizeof(std::uint64_t);
1068 flags.emplace_back(f & ~0x8000000000000000);
1069 } while (f & 0x8000000000000000);
1070
1071 return (flags.size() * sizeof(std::uint64_t));
1072}
1073
1076{
1078 return R__FAIL("locator is not serializable");
1079
1080 std::uint32_t size = 0;
1081 if ((locator.GetType() == RNTupleLocator::kTypeFile) &&
1082 (locator.GetNBytesOnStorage() <= std::numeric_limits<std::int32_t>::max())) {
1083 size += SerializeUInt32(locator.GetNBytesOnStorage(), buffer);
1084 size += SerializeUInt64(locator.GetPosition<std::uint64_t>(),
1085 buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
1086 return size;
1087 }
1088
1089 std::uint8_t locatorType = 0;
1090 auto payloadp = buffer ? reinterpret_cast<unsigned char *>(buffer) + sizeof(std::int32_t) : nullptr;
1091 switch (locator.GetType()) {
1094 locatorType = 0x01;
1095 break;
1098 locatorType = 0x02;
1099 break;
1100 default:
1101 if (locator.GetType() == ROOT::Internal::kTestLocatorType) {
1102 // For the testing locator, use the same payload as Object64. We're not gonna really read it back anyway.
1104 locatorType = 0x7e;
1105 } else {
1106 return R__FAIL("locator has unknown type");
1107 }
1108 }
1109 std::int32_t head = sizeof(std::int32_t) + size;
1110 head |= locator.GetReserved() << 16;
1111 head |= static_cast<int>(locatorType & 0x7F) << 24;
1112 head = -head;
1113 size += RNTupleSerializer::SerializeInt32(head, buffer);
1114 return size;
1115}
1116
1120{
1121 if (bufSize < sizeof(std::int32_t))
1122 return R__FAIL("too short locator");
1123
1124 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1125 std::int32_t head;
1126
1127 bytes += DeserializeInt32(bytes, head);
1128 bufSize -= sizeof(std::int32_t);
1129 if (head < 0) {
1130 head = -head;
1131 const int type = head >> 24;
1132 const std::uint32_t payloadSize = (static_cast<std::uint32_t>(head) & 0x0000FFFF) - sizeof(std::int32_t);
1133 if (bufSize < payloadSize)
1134 return R__FAIL("too short locator");
1135
1136 locator.SetReserved(static_cast<std::uint32_t>(head >> 16) & 0xFF);
1137 switch (type) {
1138 case 0x01:
1141 break;
1142 case 0x02:
1145 break;
1146 default: locator.SetType(RNTupleLocator::kTypeUnknown);
1147 }
1148 bytes += payloadSize;
1149 } else {
1150 if (bufSize < sizeof(std::uint64_t))
1151 return R__FAIL("too short locator");
1152 std::uint64_t offset;
1153 bytes += DeserializeUInt64(bytes, offset);
1155 locator.SetNBytesOnStorage(head);
1156 locator.SetPosition(offset);
1157 }
1158
1159 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1160}
1161
1164{
1165 auto size = SerializeUInt64(envelopeLink.fLength, buffer);
1166 auto res =
1167 SerializeLocator(envelopeLink.fLocator, buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
1168 if (res)
1169 size += res.Unwrap();
1170 else
1171 return R__FORWARD_ERROR(res);
1172 return size;
1173}
1174
1178{
1179 if (bufSize < sizeof(std::int64_t))
1180 return R__FAIL("too short envelope link");
1181
1182 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1183 bytes += DeserializeUInt64(bytes, envelopeLink.fLength);
1184 bufSize -= sizeof(std::uint64_t);
1185 if (auto res = DeserializeLocator(bytes, bufSize, envelopeLink.fLocator)) {
1186 bytes += res.Unwrap();
1187 } else {
1188 return R__FORWARD_ERROR(res);
1189 }
1190 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1191}
1192
1195 void *buffer)
1196{
1197 if (clusterSummary.fNEntries >= (static_cast<std::uint64_t>(1) << 56)) {
1198 return R__FAIL("number of entries in cluster exceeds maximum of 2^56");
1199 }
1200
1201 auto base = reinterpret_cast<unsigned char *>(buffer);
1202 auto pos = base;
1203 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1204
1205 auto frame = pos;
1206 pos += SerializeRecordFramePreamble(*where);
1207 pos += SerializeUInt64(clusterSummary.fFirstEntry, *where);
1208 const std::uint64_t nEntriesAndFlags =
1209 (static_cast<std::uint64_t>(clusterSummary.fFlags) << 56) | clusterSummary.fNEntries;
1210 pos += SerializeUInt64(nEntriesAndFlags, *where);
1211
1212 auto size = pos - frame;
1213 if (auto res = SerializeFramePostscript(frame, size)) {
1214 pos += res.Unwrap();
1215 } else {
1216 return R__FORWARD_ERROR(res);
1217 }
1218 return size;
1219}
1220
1224{
1225 auto base = reinterpret_cast<const unsigned char *>(buffer);
1226 auto bytes = base;
1227 std::uint64_t frameSize;
1228 if (auto res = DeserializeFrameHeader(bytes, bufSize, frameSize)) {
1229 bytes += res.Unwrap();
1230 } else {
1231 return R__FORWARD_ERROR(res);
1232 }
1233
1234 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
1235 if (fnFrameSizeLeft() < 2 * sizeof(std::uint64_t))
1236 return R__FAIL("too short cluster summary");
1237
1238 bytes += DeserializeUInt64(bytes, clusterSummary.fFirstEntry);
1239 std::uint64_t nEntriesAndFlags;
1240 bytes += DeserializeUInt64(bytes, nEntriesAndFlags);
1241
1242 const std::uint64_t nEntries = (nEntriesAndFlags << 8) >> 8;
1243 const std::uint8_t flags = nEntriesAndFlags >> 56;
1244
1245 if (flags & 0x01) {
1246 return R__FAIL("sharded cluster flag set in cluster summary; sharded clusters are currently unsupported.");
1247 }
1248
1249 clusterSummary.fNEntries = nEntries;
1250 clusterSummary.fFlags = flags;
1251
1252 return frameSize;
1253}
1254
1257{
1258 auto base = reinterpret_cast<unsigned char *>(buffer);
1259 auto pos = base;
1260 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1261
1262 auto frame = pos;
1263 pos += SerializeRecordFramePreamble(*where);
1264 pos += SerializeUInt64(clusterGroup.fMinEntry, *where);
1265 pos += SerializeUInt64(clusterGroup.fEntrySpan, *where);
1266 pos += SerializeUInt32(clusterGroup.fNClusters, *where);
1267 if (auto res = SerializeEnvelopeLink(clusterGroup.fPageListEnvelopeLink, *where)) {
1268 pos += res.Unwrap();
1269 } else {
1270 return R__FORWARD_ERROR(res);
1271 }
1272 auto size = pos - frame;
1273 if (auto res = SerializeFramePostscript(frame, size)) {
1274 return size;
1275 } else {
1276 return R__FORWARD_ERROR(res);
1277 }
1278}
1279
1283{
1284 auto base = reinterpret_cast<const unsigned char *>(buffer);
1285 auto bytes = base;
1286
1287 std::uint64_t frameSize;
1288 if (auto res = DeserializeFrameHeader(bytes, bufSize, frameSize)) {
1289 bytes += res.Unwrap();
1290 } else {
1291 return R__FORWARD_ERROR(res);
1292 }
1293
1294 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
1295 if (fnFrameSizeLeft() < sizeof(std::uint32_t) + 2 * sizeof(std::uint64_t))
1296 return R__FAIL("too short cluster group");
1297
1298 bytes += DeserializeUInt64(bytes, clusterGroup.fMinEntry);
1299 bytes += DeserializeUInt64(bytes, clusterGroup.fEntrySpan);
1300 bytes += DeserializeUInt32(bytes, clusterGroup.fNClusters);
1301 if (auto res = DeserializeEnvelopeLink(bytes, fnFrameSizeLeft(), clusterGroup.fPageListEnvelopeLink)) {
1302 bytes += res.Unwrap();
1303 } else {
1304 return R__FORWARD_ERROR(res);
1305 }
1306
1307 return frameSize;
1308}
1309
1311 bool forHeaderExtension)
1312{
1313 auto fieldZeroId = desc.GetFieldZeroId();
1314 auto depthFirstTraversal = [&](std::span<ROOT::DescriptorId_t> fieldTrees, auto doForEachField) {
1315 std::deque<ROOT::DescriptorId_t> idQueue{fieldTrees.begin(), fieldTrees.end()};
1316 while (!idQueue.empty()) {
1317 auto fieldId = idQueue.front();
1318 idQueue.pop_front();
1319 // Field zero has no physical representation nor columns of its own; recurse over its subfields only
1320 if (fieldId != fieldZeroId)
1322 unsigned i = 0;
1323 for (const auto &f : desc.GetFieldIterable(fieldId))
1324 idQueue.insert(idQueue.begin() + i++, f.GetId());
1325 }
1326 };
1327
1328 R__ASSERT(desc.GetNFields() > 0); // we must have at least a zero field
1329
1330 std::vector<ROOT::DescriptorId_t> fieldTrees;
1331 if (!forHeaderExtension) {
1332 fieldTrees.emplace_back(fieldZeroId);
1333 } else if (auto xHeader = desc.GetHeaderExtension()) {
1334 fieldTrees = xHeader->GetTopLevelFields(desc);
1335 }
1338 for (const auto &c : desc.GetColumnIterable(fieldId)) {
1339 if (!c.IsAliasColumn()) {
1340 MapPhysicalColumnId(c.GetPhysicalId());
1341 }
1342 }
1343 });
1344
1345 if (forHeaderExtension) {
1346 // Create physical IDs for column representations that extend fields of the regular header.
1347 // First the physical columns then the alias columns.
1348 for (auto memId : desc.GetHeaderExtension()->GetExtendedColumnRepresentations()) {
1349 const auto &columnDesc = desc.GetColumnDescriptor(memId);
1350 if (!columnDesc.IsAliasColumn()) {
1351 MapPhysicalColumnId(columnDesc.GetPhysicalId());
1352 }
1353 }
1354 }
1355}
1356
1358 void *buffer, const ROOT::RNTupleDescriptor &desc, const RContext &context, bool forHeaderExtension)
1359{
1360 auto base = reinterpret_cast<unsigned char *>(buffer);
1361 auto pos = base;
1362 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1363
1364 std::size_t nFields = 0, nColumns = 0, nAliasColumns = 0, fieldListOffset = 0;
1365 // Columns in the extension header that are attached to a field of the regular header
1366 std::vector<std::reference_wrapper<const ROOT::RColumnDescriptor>> extraColumns;
1367 if (forHeaderExtension) {
1368 // A call to `RNTupleDescriptorBuilder::BeginHeaderExtension()` is not strictly required after serializing the
1369 // header, which may happen, e.g., in unit tests. Ensure an empty schema extension is serialized in this case
1370 if (auto xHeader = desc.GetHeaderExtension()) {
1371 nFields = xHeader->GetNFields();
1372 nColumns = xHeader->GetNPhysicalColumns();
1373 nAliasColumns = xHeader->GetNLogicalColumns() - xHeader->GetNPhysicalColumns();
1374 fieldListOffset = desc.GetNFields() - nFields - 1;
1375
1376 extraColumns.reserve(xHeader->GetExtendedColumnRepresentations().size());
1377 for (auto columnId : xHeader->GetExtendedColumnRepresentations()) {
1378 extraColumns.emplace_back(desc.GetColumnDescriptor(columnId));
1379 }
1380 }
1381 } else {
1382 if (auto xHeader = desc.GetHeaderExtension()) {
1383 nFields = desc.GetNFields() - xHeader->GetNFields() - 1;
1384 nColumns = desc.GetNPhysicalColumns() - xHeader->GetNPhysicalColumns();
1386 (xHeader->GetNLogicalColumns() - xHeader->GetNPhysicalColumns());
1387 } else {
1388 nFields = desc.GetNFields() - 1;
1391 }
1392 }
1393 const auto nExtraTypeInfos = desc.GetNExtraTypeInfos();
1394 const auto &onDiskFields = context.GetOnDiskFieldList();
1396 std::span<const ROOT::DescriptorId_t> fieldList{onDiskFields.data() + fieldListOffset, nFields};
1397
1398 auto frame = pos;
1399 pos += SerializeListFramePreamble(nFields, *where);
1400 if (auto res = SerializeFieldList(desc, fieldList, /*firstOnDiskId=*/fieldListOffset, context, *where)) {
1401 pos += res.Unwrap();
1402 } else {
1403 return R__FORWARD_ERROR(res);
1404 }
1405 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1406 pos += res.Unwrap();
1407 } else {
1408 return R__FORWARD_ERROR(res);
1409 }
1410
1411 frame = pos;
1412 pos += SerializeListFramePreamble(nColumns, *where);
1413 if (auto res = SerializeColumnsOfFields(desc, fieldList, context, *where, forHeaderExtension)) {
1414 pos += res.Unwrap();
1415 } else {
1416 return R__FORWARD_ERROR(res);
1417 }
1418 for (const auto &c : extraColumns) {
1419 if (!c.get().IsAliasColumn()) {
1420 if (auto res = SerializePhysicalColumn(c.get(), context, *where)) {
1421 pos += res.Unwrap();
1422 } else {
1423 return R__FORWARD_ERROR(res);
1424 }
1425 }
1426 }
1427 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1428 pos += res.Unwrap();
1429 } else {
1430 return R__FORWARD_ERROR(res);
1431 }
1432
1433 frame = pos;
1434 pos += SerializeListFramePreamble(nAliasColumns, *where);
1436 for (const auto &c : extraColumns) {
1437 if (c.get().IsAliasColumn()) {
1438 pos += SerializeAliasColumn(c.get(), context, *where);
1439 }
1440 }
1441 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1442 pos += res.Unwrap();
1443 } else {
1444 return R__FORWARD_ERROR(res);
1445 }
1446
1447 frame = pos;
1448 // We only serialize the extra type info list in the header extension.
1449 if (forHeaderExtension) {
1450 pos += SerializeListFramePreamble(nExtraTypeInfos, *where);
1451 if (auto res = SerializeExtraTypeInfoList(desc, *where)) {
1452 pos += res.Unwrap();
1453 } else {
1454 return R__FORWARD_ERROR(res);
1455 }
1456 } else {
1457 pos += SerializeListFramePreamble(0, *where);
1458 }
1459 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1460 pos += res.Unwrap();
1461 } else {
1462 return R__FORWARD_ERROR(res);
1463 }
1464
1465 return static_cast<std::uint32_t>(pos - base);
1466}
1467
1471{
1472 auto base = reinterpret_cast<const unsigned char *>(buffer);
1473 auto bytes = base;
1474 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1475
1476 std::uint64_t frameSize;
1477 auto frame = bytes;
1478 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
1479
1480 std::uint32_t nFields;
1481 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nFields)) {
1482 bytes += res.Unwrap();
1483 } else {
1484 return R__FORWARD_ERROR(res);
1485 }
1486 // The zero field is always added before `DeserializeSchemaDescription()` is called
1487 const std::uint32_t fieldIdRangeBegin = descBuilder.GetDescriptor().GetNFields() - 1;
1488 for (unsigned i = 0; i < nFields; ++i) {
1489 std::uint32_t fieldId = fieldIdRangeBegin + i;
1491 if (auto res = DeserializeField(bytes, fnFrameSizeLeft(), fieldBuilder)) {
1492 bytes += res.Unwrap();
1493 } else {
1494 return R__FORWARD_ERROR(res);
1495 }
1496 if (fieldId == fieldBuilder.GetParentId())
1497 fieldBuilder.ParentId(kZeroFieldId);
1498 auto fieldDesc = fieldBuilder.FieldId(fieldId).MakeDescriptor();
1499 if (!fieldDesc)
1501 const auto parentId = fieldDesc.Inspect().GetParentId();
1502 const auto projectionSourceId = fieldDesc.Inspect().GetProjectionSourceId();
1503 descBuilder.AddField(fieldDesc.Unwrap());
1504 auto resVoid = descBuilder.AddFieldLink(parentId, fieldId);
1505 if (!resVoid)
1506 return R__FORWARD_ERROR(resVoid);
1508 resVoid = descBuilder.AddFieldProjection(projectionSourceId, fieldId);
1509 if (!resVoid)
1510 return R__FORWARD_ERROR(resVoid);
1511 }
1512 }
1513 bytes = frame + frameSize;
1514
1515 // As columns are added in order of representation index and column index, determine the column index
1516 // for the currently deserialized column from the columns already added.
1518 std::uint16_t representationIndex) -> std::uint32_t {
1519 const auto &existingColumns = descBuilder.GetDescriptor().GetFieldDescriptor(fieldId).GetLogicalColumnIds();
1520 if (existingColumns.empty())
1521 return 0;
1522 const auto &lastColumnDesc = descBuilder.GetDescriptor().GetColumnDescriptor(existingColumns.back());
1523 return (representationIndex == lastColumnDesc.GetRepresentationIndex()) ? (lastColumnDesc.GetIndex() + 1) : 0;
1524 };
1525
1526 std::uint32_t nColumns;
1527 frame = bytes;
1528 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nColumns)) {
1529 bytes += res.Unwrap();
1530 } else {
1531 return R__FORWARD_ERROR(res);
1532 }
1533
1534 if (descBuilder.GetDescriptor().GetNLogicalColumns() > descBuilder.GetDescriptor().GetNPhysicalColumns())
1535 descBuilder.ShiftAliasColumns(nColumns);
1536
1537 const std::uint32_t columnIdRangeBegin = descBuilder.GetDescriptor().GetNPhysicalColumns();
1538 for (unsigned i = 0; i < nColumns; ++i) {
1539 std::uint32_t columnId = columnIdRangeBegin + i;
1542 bytes += res.Unwrap();
1543 } else {
1544 return R__FORWARD_ERROR(res);
1545 }
1546
1547 columnBuilder.Index(fnNextColumnIndex(columnBuilder.GetFieldId(), columnBuilder.GetRepresentationIndex()));
1548 columnBuilder.LogicalColumnId(columnId);
1549 columnBuilder.PhysicalColumnId(columnId);
1550 auto columnDesc = columnBuilder.MakeDescriptor();
1551 if (!columnDesc)
1553 auto resVoid = descBuilder.AddColumn(columnDesc.Unwrap());
1554 if (!resVoid)
1555 return R__FORWARD_ERROR(resVoid);
1556 }
1557 bytes = frame + frameSize;
1558
1559 std::uint32_t nAliasColumns;
1560 frame = bytes;
1561 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nAliasColumns)) {
1562 bytes += res.Unwrap();
1563 } else {
1564 return R__FORWARD_ERROR(res);
1565 }
1566 const std::uint32_t aliasColumnIdRangeBegin = descBuilder.GetDescriptor().GetNLogicalColumns();
1567 for (unsigned i = 0; i < nAliasColumns; ++i) {
1568 std::uint32_t physicalId;
1569 std::uint32_t fieldId;
1571 bytes += res.Unwrap();
1572 } else {
1573 return R__FORWARD_ERROR(res);
1574 }
1575
1577 columnBuilder.LogicalColumnId(aliasColumnIdRangeBegin + i).PhysicalColumnId(physicalId).FieldId(fieldId);
1578 const auto &physicalColumnDesc = descBuilder.GetDescriptor().GetColumnDescriptor(physicalId);
1579 columnBuilder.BitsOnStorage(physicalColumnDesc.GetBitsOnStorage());
1580 columnBuilder.ValueRange(physicalColumnDesc.GetValueRange());
1581 columnBuilder.Type(physicalColumnDesc.GetType());
1582 columnBuilder.RepresentationIndex(physicalColumnDesc.GetRepresentationIndex());
1583 columnBuilder.Index(fnNextColumnIndex(columnBuilder.GetFieldId(), columnBuilder.GetRepresentationIndex()));
1584
1585 auto aliasColumnDesc = columnBuilder.MakeDescriptor();
1586 if (!aliasColumnDesc)
1588 auto resVoid = descBuilder.AddColumn(aliasColumnDesc.Unwrap());
1589 if (!resVoid)
1590 return R__FORWARD_ERROR(resVoid);
1591 }
1592 bytes = frame + frameSize;
1593
1594 std::uint32_t nExtraTypeInfos;
1595 frame = bytes;
1596 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nExtraTypeInfos)) {
1597 bytes += res.Unwrap();
1598 } else {
1599 return R__FORWARD_ERROR(res);
1600 }
1601 for (unsigned i = 0; i < nExtraTypeInfos; ++i) {
1604 bytes += res.Unwrap();
1605 } else {
1606 return R__FORWARD_ERROR(res);
1607 }
1608
1609 auto extraTypeInfoDesc = extraTypeInfoBuilder.MoveDescriptor();
1610 // We ignore unknown extra type information
1612 descBuilder.AddExtraTypeInfo(extraTypeInfoDesc.Unwrap());
1613 }
1614 bytes = frame + frameSize;
1615
1616 return bytes - base;
1617}
1618
1621{
1622 RContext context;
1623
1624 auto base = reinterpret_cast<unsigned char *>(buffer);
1625 auto pos = base;
1626 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1627
1628 pos += SerializeEnvelopePreamble(kEnvelopeTypeHeader, *where);
1629 // So far we don't make use of feature flags
1630 if (auto res = SerializeFeatureFlags(desc.GetFeatureFlags(), *where)) {
1631 pos += res.Unwrap();
1632 } else {
1633 return R__FORWARD_ERROR(res);
1634 }
1635 pos += SerializeString(desc.GetName(), *where);
1636 pos += SerializeString(desc.GetDescription(), *where);
1637 pos += SerializeString(std::string("ROOT v") + ROOT_RELEASE, *where);
1638
1639 context.MapSchema(desc, /*forHeaderExtension=*/false);
1640
1641 if (auto res = SerializeSchemaDescription(*where, desc, context)) {
1642 pos += res.Unwrap();
1643 } else {
1644 return R__FORWARD_ERROR(res);
1645 }
1646
1647 std::uint64_t size = pos - base;
1648 std::uint64_t xxhash3 = 0;
1649 if (auto res = SerializeEnvelopePostscript(base, size, xxhash3)) {
1650 size += res.Unwrap();
1651 } else {
1652 return R__FORWARD_ERROR(res);
1653 }
1654
1655 context.SetHeaderSize(size);
1656 context.SetHeaderXxHash3(xxhash3);
1657 return context;
1658}
1659
1662 std::span<ROOT::DescriptorId_t> physClusterIDs,
1663 const RContext &context)
1664{
1665 auto base = reinterpret_cast<unsigned char *>(buffer);
1666 auto pos = base;
1667 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1668
1669 pos += SerializeEnvelopePreamble(kEnvelopeTypePageList, *where);
1670
1671 pos += SerializeUInt64(context.GetHeaderXxHash3(), *where);
1672
1673 // Cluster summaries
1674 const auto nClusters = physClusterIDs.size();
1675 auto clusterSummaryFrame = pos;
1676 pos += SerializeListFramePreamble(nClusters, *where);
1677 for (auto clusterId : physClusterIDs) {
1678 const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1679 RClusterSummary summary{clusterDesc.GetFirstEntryIndex(), clusterDesc.GetNEntries(), 0};
1680 if (auto res = SerializeClusterSummary(summary, *where)) {
1681 pos += res.Unwrap();
1682 } else {
1683 return R__FORWARD_ERROR(res);
1684 }
1685 }
1686 if (auto res = SerializeFramePostscript(buffer ? clusterSummaryFrame : nullptr, pos - clusterSummaryFrame)) {
1687 pos += res.Unwrap();
1688 } else {
1689 return R__FORWARD_ERROR(res);
1690 }
1691
1692 // Page locations
1693 auto topMostFrame = pos;
1694 pos += SerializeListFramePreamble(nClusters, *where);
1695
1696 for (auto clusterId : physClusterIDs) {
1697 const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1698 // Get an ordered set of physical column ids
1699 std::set<ROOT::DescriptorId_t> onDiskColumnIds;
1700 for (const auto &columnRange : clusterDesc.GetColumnRangeIterable())
1701 onDiskColumnIds.insert(context.GetOnDiskColumnId(columnRange.GetPhysicalColumnId()));
1702
1703 auto outerFrame = pos;
1704 pos += SerializeListFramePreamble(onDiskColumnIds.size(), *where);
1705 for (auto onDiskId : onDiskColumnIds) {
1706 auto memId = context.GetMemColumnId(onDiskId);
1707 const auto &columnRange = clusterDesc.GetColumnRange(memId);
1708
1709 auto innerFrame = pos;
1710 if (columnRange.IsSuppressed()) {
1711 // Empty page range
1712 pos += SerializeListFramePreamble(0, *where);
1713 pos += SerializeInt64(kSuppressedColumnMarker, *where);
1714 } else {
1715 const auto &pageRange = clusterDesc.GetPageRange(memId);
1716 pos += SerializeListFramePreamble(pageRange.GetPageInfos().size(), *where);
1717
1718 for (const auto &pi : pageRange.GetPageInfos()) {
1719 std::int32_t nElements =
1720 pi.HasChecksum() ? -static_cast<std::int32_t>(pi.GetNElements()) : pi.GetNElements();
1721 pos += SerializeUInt32(nElements, *where);
1722 if (auto res = SerializeLocator(pi.GetLocator(), *where)) {
1723 pos += res.Unwrap();
1724 } else {
1725 return R__FORWARD_ERROR(res);
1726 }
1727 }
1728 pos += SerializeInt64(columnRange.GetFirstElementIndex(), *where);
1729 pos += SerializeUInt32(columnRange.GetCompressionSettings().value(), *where);
1730 }
1731
1732 if (auto res = SerializeFramePostscript(buffer ? innerFrame : nullptr, pos - innerFrame)) {
1733 pos += res.Unwrap();
1734 } else {
1735 return R__FORWARD_ERROR(res);
1736 }
1737 }
1738 if (auto res = SerializeFramePostscript(buffer ? outerFrame : nullptr, pos - outerFrame)) {
1739 pos += res.Unwrap();
1740 } else {
1741 return R__FORWARD_ERROR(res);
1742 }
1743 }
1744
1745 if (auto res = SerializeFramePostscript(buffer ? topMostFrame : nullptr, pos - topMostFrame)) {
1746 pos += res.Unwrap();
1747 } else {
1748 return R__FORWARD_ERROR(res);
1749 }
1750 std::uint64_t size = pos - base;
1751 if (auto res = SerializeEnvelopePostscript(base, size)) {
1752 size += res.Unwrap();
1753 } else {
1754 return R__FORWARD_ERROR(res);
1755 }
1756 return size;
1757}
1758
1761 const RContext &context)
1762{
1763 auto base = reinterpret_cast<unsigned char *>(buffer);
1764 auto pos = base;
1765 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1766
1767 pos += SerializeEnvelopePreamble(kEnvelopeTypeFooter, *where);
1768
1769 // So far we don't make use of footer feature flags
1770 if (auto res = SerializeFeatureFlags(std::vector<std::uint64_t>(), *where)) {
1771 pos += res.Unwrap();
1772 } else {
1773 return R__FORWARD_ERROR(res);
1774 }
1775 pos += SerializeUInt64(context.GetHeaderXxHash3(), *where);
1776
1777 // Schema extension, i.e. incremental changes with respect to the header
1778 auto frame = pos;
1779 pos += SerializeRecordFramePreamble(*where);
1780 if (auto res = SerializeSchemaDescription(*where, desc, context, /*forHeaderExtension=*/true)) {
1781 pos += res.Unwrap();
1782 } else {
1783 return R__FORWARD_ERROR(res);
1784 }
1785 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1786 pos += res.Unwrap();
1787 } else {
1788 return R__FORWARD_ERROR(res);
1789 }
1790
1791 // Cluster groups
1792 frame = pos;
1793 const auto nClusterGroups = desc.GetNClusterGroups();
1794 pos += SerializeListFramePreamble(nClusterGroups, *where);
1795 for (unsigned int i = 0; i < nClusterGroups; ++i) {
1796 const auto &cgDesc = desc.GetClusterGroupDescriptor(context.GetMemClusterGroupId(i));
1798 clusterGroup.fMinEntry = cgDesc.GetMinEntry();
1799 clusterGroup.fEntrySpan = cgDesc.GetEntrySpan();
1800 clusterGroup.fNClusters = cgDesc.GetNClusters();
1801 clusterGroup.fPageListEnvelopeLink.fLength = cgDesc.GetPageListLength();
1802 clusterGroup.fPageListEnvelopeLink.fLocator = cgDesc.GetPageListLocator();
1803 if (auto res = SerializeClusterGroup(clusterGroup, *where)) {
1804 pos += res.Unwrap();
1805 } else {
1806 return R__FORWARD_ERROR(res);
1807 }
1808 }
1809 if (auto res = SerializeFramePostscript(buffer ? frame : nullptr, pos - frame)) {
1810 pos += res.Unwrap();
1811 } else {
1812 return R__FORWARD_ERROR(res);
1813 }
1814
1815 std::uint32_t size = pos - base;
1816 if (auto res = SerializeEnvelopePostscript(base, size)) {
1817 size += res.Unwrap();
1818 } else {
1819 return R__FORWARD_ERROR(res);
1820 }
1821 return size;
1822}
1823
1827{
1828 auto base = reinterpret_cast<const unsigned char *>(buffer);
1829 auto bytes = base;
1830 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1831
1832 std::uint64_t xxhash3{0};
1833 if (auto res = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypeHeader, xxhash3)) {
1834 bytes += res.Unwrap();
1835 } else {
1836 return R__FORWARD_ERROR(res);
1837 }
1838 descBuilder.SetOnDiskHeaderXxHash3(xxhash3);
1839
1840 std::vector<std::uint64_t> featureFlags;
1841 if (auto res = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags)) {
1842 bytes += res.Unwrap();
1843 } else {
1844 return R__FORWARD_ERROR(res);
1845 }
1846 for (std::size_t i = 0; i < featureFlags.size(); ++i) {
1847 if (!featureFlags[i])
1848 continue;
1849 unsigned int bit = 0;
1850 while (!(featureFlags[i] & (static_cast<uint64_t>(1) << bit)))
1851 bit++;
1852 return R__FAIL("unsupported format feature: " + std::to_string(i * 64 + bit));
1853 }
1854
1855 std::string name;
1856 std::string description;
1857 std::string writer;
1858 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), name)) {
1859 bytes += res.Unwrap();
1860 } else {
1861 return R__FORWARD_ERROR(res);
1862 }
1863 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), description)) {
1864 bytes += res.Unwrap();
1865 } else {
1866 return R__FORWARD_ERROR(res);
1867 }
1868 if (auto res = DeserializeString(bytes, fnBufSizeLeft(), writer)) {
1869 bytes += res.Unwrap();
1870 } else {
1871 return R__FORWARD_ERROR(res);
1872 }
1873 descBuilder.SetNTuple(name, description);
1874
1875 // Zero field
1877 .FieldId(kZeroFieldId)
1879 .MakeDescriptor()
1880 .Unwrap());
1881 if (auto res = DeserializeSchemaDescription(bytes, fnBufSizeLeft(), descBuilder)) {
1882 return RResult<void>::Success();
1883 } else {
1884 return R__FORWARD_ERROR(res);
1885 }
1886}
1887
1891{
1892 auto base = reinterpret_cast<const unsigned char *>(buffer);
1893 auto bytes = base;
1894 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1895 if (auto res = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypeFooter)) {
1896 bytes += res.Unwrap();
1897 } else {
1898 return R__FORWARD_ERROR(res);
1899 }
1900
1901 std::vector<std::uint64_t> featureFlags;
1902 if (auto res = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags)) {
1903 bytes += res.Unwrap();
1904 } else {
1905 return R__FORWARD_ERROR(res);
1906 }
1907 for (auto f : featureFlags) {
1908 if (f)
1909 R__LOG_WARNING(ROOT::Internal::NTupleLog()) << "Unsupported feature flag! " << f;
1910 }
1911
1912 std::uint64_t xxhash3{0};
1913 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
1914 return R__FAIL("footer too short");
1915 bytes += DeserializeUInt64(bytes, xxhash3);
1916 if (xxhash3 != descBuilder.GetDescriptor().GetOnDiskHeaderXxHash3())
1917 return R__FAIL("XxHash-3 mismatch between header and footer");
1918
1919 std::uint64_t frameSize;
1920 auto frame = bytes;
1921 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
1922
1923 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize)) {
1924 bytes += res.Unwrap();
1925 } else {
1926 return R__FORWARD_ERROR(res);
1927 }
1928 if (fnFrameSizeLeft() > 0) {
1929 descBuilder.BeginHeaderExtension();
1930 if (auto res = DeserializeSchemaDescription(bytes, fnFrameSizeLeft(), descBuilder); !res) {
1931 return R__FORWARD_ERROR(res);
1932 }
1933 }
1934 bytes = frame + frameSize;
1935
1936 std::uint32_t nClusterGroups;
1937 frame = bytes;
1938 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nClusterGroups)) {
1939 bytes += res.Unwrap();
1940 } else {
1941 return R__FORWARD_ERROR(res);
1942 }
1943 for (std::uint32_t groupId = 0; groupId < nClusterGroups; ++groupId) {
1945 if (auto res = DeserializeClusterGroup(bytes, fnFrameSizeLeft(), clusterGroup)) {
1946 bytes += res.Unwrap();
1947 } else {
1948 return R__FORWARD_ERROR(res);
1949 }
1950
1951 descBuilder.AddToOnDiskFooterSize(clusterGroup.fPageListEnvelopeLink.fLocator.GetNBytesOnStorage());
1953 clusterGroupBuilder.ClusterGroupId(groupId)
1954 .PageListLocator(clusterGroup.fPageListEnvelopeLink.fLocator)
1955 .PageListLength(clusterGroup.fPageListEnvelopeLink.fLength)
1956 .MinEntry(clusterGroup.fMinEntry)
1957 .EntrySpan(clusterGroup.fEntrySpan)
1958 .NClusters(clusterGroup.fNClusters);
1959 descBuilder.AddClusterGroup(clusterGroupBuilder.MoveDescriptor().Unwrap());
1960 }
1961 bytes = frame + frameSize;
1962
1963 return RResult<void>::Success();
1964}
1965
1969 const ROOT::RNTupleDescriptor &desc)
1970{
1971 auto base = reinterpret_cast<const unsigned char *>(buffer);
1972 auto bytes = base;
1973 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1974
1975 if (auto res = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypePageList)) {
1976 bytes += res.Unwrap();
1977 } else {
1978 return R__FORWARD_ERROR(res);
1979 }
1980
1981 std::uint64_t xxhash3{0};
1982 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
1983 return R__FAIL("page list too short");
1984 bytes += DeserializeUInt64(bytes, xxhash3);
1985 if (xxhash3 != desc.GetOnDiskHeaderXxHash3())
1986 return R__FAIL("XxHash-3 mismatch between header and page list");
1987
1988 std::vector<RClusterDescriptorBuilder> clusterBuilders;
1990 for (ROOT::DescriptorId_t i = 0; i < clusterGroupId; ++i) {
1991 firstClusterId = firstClusterId + desc.GetClusterGroupDescriptor(i).GetNClusters();
1992 }
1993
1994 std::uint64_t clusterSummaryFrameSize;
1997
1998 std::uint32_t nClusterSummaries;
1999 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), clusterSummaryFrameSize, nClusterSummaries)) {
2000 bytes += res.Unwrap();
2001 } else {
2002 return R__FORWARD_ERROR(res);
2003 }
2006 if (auto res = DeserializeClusterSummary(bytes, fnClusterSummaryFrameSizeLeft(), clusterSummary)) {
2007 bytes += res.Unwrap();
2008 } else {
2009 return R__FORWARD_ERROR(res);
2010 }
2011
2014 clusterBuilders.emplace_back(std::move(builder));
2015 }
2017
2018 std::uint64_t topMostFrameSize;
2019 auto topMostFrame = bytes;
2020 auto fnTopMostFrameSizeLeft = [&]() { return topMostFrameSize - (bytes - topMostFrame); };
2021
2022 std::uint32_t nClusters;
2023 if (auto res = DeserializeFrameHeader(bytes, fnBufSizeLeft(), topMostFrameSize, nClusters)) {
2024 bytes += res.Unwrap();
2025 } else {
2026 return R__FORWARD_ERROR(res);
2027 }
2028
2030 return R__FAIL("mismatch between number of clusters and number of cluster summaries");
2031
2032 for (std::uint32_t i = 0; i < nClusters; ++i) {
2033 std::uint64_t outerFrameSize;
2034 auto outerFrame = bytes;
2035 auto fnOuterFrameSizeLeft = [&]() { return outerFrameSize - (bytes - outerFrame); };
2036
2037 std::uint32_t nColumns;
2038 if (auto res = DeserializeFrameHeader(bytes, fnTopMostFrameSizeLeft(), outerFrameSize, nColumns)) {
2039 bytes += res.Unwrap();
2040 } else {
2041 return R__FORWARD_ERROR(res);
2042 }
2043
2044 for (std::uint32_t j = 0; j < nColumns; ++j) {
2045 std::uint64_t innerFrameSize;
2046 auto innerFrame = bytes;
2047 auto fnInnerFrameSizeLeft = [&]() { return innerFrameSize - (bytes - innerFrame); };
2048
2049 std::uint32_t nPages;
2050 if (auto res = DeserializeFrameHeader(bytes, fnOuterFrameSizeLeft(), innerFrameSize, nPages)) {
2051 bytes += res.Unwrap();
2052 } else {
2053 return R__FORWARD_ERROR(res);
2054 }
2055
2057 pageRange.SetPhysicalColumnId(j);
2058 for (std::uint32_t k = 0; k < nPages; ++k) {
2059 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
2060 return R__FAIL("inner frame too short");
2061 std::int32_t nElements;
2062 bool hasChecksum = false;
2064 bytes += DeserializeInt32(bytes, nElements);
2065 if (nElements < 0) {
2067 hasChecksum = true;
2068 }
2069 if (auto res = DeserializeLocator(bytes, fnInnerFrameSizeLeft(), locator)) {
2070 bytes += res.Unwrap();
2071 } else {
2072 return R__FORWARD_ERROR(res);
2073 }
2074 pageRange.GetPageInfos().push_back({static_cast<std::uint32_t>(nElements), locator, hasChecksum});
2075 }
2076
2077 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::int64_t)))
2078 return R__FAIL("page list frame too short");
2079 std::int64_t columnOffset;
2080 bytes += DeserializeInt64(bytes, columnOffset);
2081 if (columnOffset < 0) {
2082 if (nPages > 0)
2083 return R__FAIL("unexpected non-empty page list");
2084 clusterBuilders[i].MarkSuppressedColumnRange(j);
2085 } else {
2086 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
2087 return R__FAIL("page list frame too short");
2088 std::uint32_t compressionSettings;
2089 bytes += DeserializeUInt32(bytes, compressionSettings);
2091 }
2092
2094 } // loop over columns
2095
2097 } // loop over clusters
2098
2099 return clusterBuilders;
2100}
2101
2107{
2109 if (!clusterBuildersRes)
2111
2112 auto clusterBuilders = clusterBuildersRes.Unwrap();
2113
2114 std::vector<ROOT::RClusterDescriptor> clusters;
2115 clusters.reserve(clusterBuilders.size());
2116
2117 // Conditionally fixup the clusters depending on the attach purpose
2118 switch (mode) {
2119 case EDescriptorDeserializeMode::kForReading:
2120 for (auto &builder : clusterBuilders) {
2121 if (auto res = builder.CommitSuppressedColumnRanges(desc); !res)
2122 return R__FORWARD_RESULT(res);
2123 builder.AddExtendedColumnRanges(desc);
2124 clusters.emplace_back(builder.MoveDescriptor().Unwrap());
2125 }
2126 break;
2127 case EDescriptorDeserializeMode::kForWriting:
2128 for (auto &builder : clusterBuilders) {
2129 if (auto res = builder.CommitSuppressedColumnRanges(desc); !res)
2130 return R__FORWARD_RESULT(res);
2131 clusters.emplace_back(builder.MoveDescriptor().Unwrap());
2132 }
2133 break;
2134 case EDescriptorDeserializeMode::kRaw:
2135 for (auto &builder : clusterBuilders)
2136 clusters.emplace_back(builder.MoveDescriptor().Unwrap());
2137 break;
2138 }
2139
2141
2142 return RResult<void>::Success();
2143}
2144
2146{
2148 for (auto si : infos) {
2149 assert(si.first == si.second->GetNumber());
2150 streamerInfos.Add(si.second);
2151 }
2153 buffer.WriteObject(&streamerInfos);
2154 assert(buffer.Length() > 0);
2155 return std::string{buffer.Buffer(), static_cast<UInt_t>(buffer.Length())};
2156}
2157
2160{
2162
2163 TBufferFile buffer(TBuffer::kRead, extraTypeInfoContent.length(), const_cast<char *>(extraTypeInfoContent.data()),
2164 false /* adopt */);
2165 auto infoList = reinterpret_cast<TList *>(buffer.ReadObject(TList::Class()));
2166 infoList->SetOwner(); // delete the TStreamerInfo items of the list
2167
2168 TObjLink *lnk = infoList->FirstLink();
2169 while (lnk) {
2170 auto info = reinterpret_cast<TStreamerInfo *>(lnk->GetObject());
2171 info->BuildCheck();
2172 infoMap[info->GetNumber()] = info->GetClass()->GetStreamerInfo();
2173 assert(info->GetNumber() == infoMap[info->GetNumber()]->GetNumber());
2174 lnk = lnk->Next();
2175 }
2176
2177 delete infoList;
2178
2179 return infoMap;
2180}
#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:358
#define R__LOG_DEBUG(DEBUGLEVEL,...)
Definition RLogger.hxx:360
#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:110
The available trivial, native content types of a column.
The serialization context is used for the piecewise serialization of a descriptor.
ROOT::DescriptorId_t GetMemClusterGroupId(ROOT::DescriptorId_t onDiskId) const
ROOT::DescriptorId_t GetOnDiskFieldId(ROOT::DescriptorId_t memId) const
ROOT::DescriptorId_t GetOnDiskColumnId(ROOT::DescriptorId_t memId) const
ROOT::DescriptorId_t GetMemClusterId(ROOT::DescriptorId_t onDiskId) const
ROOT::DescriptorId_t GetMemColumnId(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,...
void MapSchema(const RNTupleDescriptor &desc, bool forHeaderExtension)
Map in-memory field and column IDs to their on-disk counterparts.
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::uint32_t > DeserializeColumnType(const void *buffer, ROOT::ENTupleColumnType &type)
static std::uint32_t SerializeListFramePreamble(std::uint32_t nitems, void *buffer)
static RResult< std::uint32_t > DeserializeExtraTypeInfoId(const void *buffer, ROOT::EExtraTypeInfoIds &id)
static RResult< std::uint32_t > SerializeFramePostscript(void *frame, std::uint64_t size)
static RResult< std::uint32_t > DeserializeFieldStructure(const void *buffer, ROOT::ENTupleStructure &structure)
static RResult< StreamerInfoMap_t > DeserializeStreamerInfos(const std::string &extraTypeInfoContent)
static RResult< std::uint32_t > SerializeLocator(const RNTupleLocator &locator, void *buffer)
static RResult< std::uint32_t > SerializeEnvelopePostscript(unsigned char *envelope, std::uint64_t size)
static RResult< std::uint32_t > DeserializeEnvelope(const void *buffer, std::uint64_t bufSize, std::uint16_t expectedType)
static std::uint32_t DeserializeUInt16(const void *buffer, std::uint16_t &val)
static RResult< std::uint32_t > DeserializeString(const void *buffer, std::uint64_t bufSize, std::string &val)
static RResult< std::uint32_t > DeserializeFeatureFlags(const void *buffer, std::uint64_t bufSize, std::vector< std::uint64_t > &flags)
static std::uint32_t SerializeString(const std::string &val, void *buffer)
static std::string SerializeStreamerInfos(const StreamerInfoMap_t &infos)
static RResult< void > DeserializeFooter(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RNTupleDescriptorBuilder &descBuilder)
static RResult< std::uint32_t > SerializeClusterGroup(const RClusterGroup &clusterGroup, void *buffer)
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 > 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 > DeserializeEnvelopeLink(const void *buffer, std::uint64_t bufSize, REnvelopeLink &envelopeLink)
static std::uint32_t DeserializeUInt32(const void *buffer, std::uint32_t &val)
static std::uint32_t SerializeUInt64(std::uint64_t val, void *buffer)
static std::uint32_t SerializeEnvelopePreamble(std::uint16_t envelopeType, void *buffer)
static std::uint32_t DeserializeInt16(const void *buffer, std::int16_t &val)
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 > SerializeExtraTypeInfoId(ROOT::EExtraTypeInfoIds id, void *buffer)
static std::uint32_t SerializeInt16(std::int16_t val, void *buffer)
static RResult< std::uint32_t > SerializeFeatureFlags(const std::vector< std::uint64_t > &flags, void *buffer)
static RResult< std::uint32_t > SerializePageList(void *buffer, const RNTupleDescriptor &desc, std::span< ROOT::DescriptorId_t > physClusterIDs, const RContext &context)
std::map< Int_t, TVirtualStreamerInfo * > StreamerInfoMap_t
static std::uint32_t SerializeInt32(std::int32_t val, void *buffer)
static std::uint32_t DeserializeUInt64(const void *buffer, std::uint64_t &val)
static RResult< std::uint32_t > SerializeFooter(void *buffer, const RNTupleDescriptor &desc, const RContext &context)
static std::uint32_t DeserializeInt32(const void *buffer, std::int32_t &val)
static std::uint32_t DeserializeInt64(const void *buffer, std::int64_t &val)
static RResult< std::uint32_t > DeserializeClusterGroup(const void *buffer, std::uint64_t bufSize, RClusterGroup &clusterGroup)
static RResult< std::uint32_t > SerializeColumnType(ROOT::ENTupleColumnType type, void *buffer)
static std::uint32_t SerializeRecordFramePreamble(void *buffer)
static std::uint32_t SerializeUInt16(std::uint16_t val, void *buffer)
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 > DeserializeLocator(const void *buffer, std::uint64_t bufSize, RNTupleLocator &locator)
static RResult< std::uint32_t > SerializeEnvelopeLink(const REnvelopeLink &envelopeLink, void *buffer)
static RResult< std::uint32_t > DeserializeSchemaDescription(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RNTupleDescriptorBuilder &descBuilder)
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 std::uint32_t SerializeInt64(std::int64_t val, void *buffer)
static RResult< std::uint32_t > DeserializeClusterSummary(const void *buffer, std::uint64_t bufSize, RClusterSummary &clusterSummary)
static std::uint32_t SerializeUInt32(std::uint32_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 > DeserializeHeader(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RNTupleDescriptorBuilder &descBuilder)
static RResult< std::uint32_t > SerializeClusterSummary(const RClusterSummary &clusterSummary, void *buffer)
static RResult< RContext > SerializeHeader(void *buffer, const RNTupleDescriptor &desc)
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.
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 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)
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.
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
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 ntuple model tree can carry different structural information about the type system.