Logo ROOT  
Reference Guide
 
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 "RColumnElement.hxx"
24
25#include <RVersion.h>
26#include <TBufferFile.h>
27#include <TClass.h>
28#include <TList.h>
29#include <TStreamerInfo.h>
31#include <xxhash.h>
32
33#include <cassert>
34#include <cmath>
35#include <cstring> // for memcpy
36#include <deque>
37#include <functional>
38#include <limits>
39#include <set>
40#include <unordered_map>
41
42template <typename T>
44
45namespace {
47
48std::uint32_t SerializeField(const ROOT::Experimental::RFieldDescriptor &fieldDesc,
50 ROOT::Experimental::DescriptorId_t onDiskProjectionSourceId, void *buffer)
51{
52
53 auto base = reinterpret_cast<unsigned char *>(buffer);
54 auto pos = base;
55 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
56
57 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
58
59 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetFieldVersion(), *where);
60 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetTypeVersion(), *where);
61 pos += RNTupleSerializer::SerializeUInt32(onDiskParentId, *where);
62 pos += RNTupleSerializer::SerializeFieldStructure(fieldDesc.GetStructure(), *where);
63
64 std::uint16_t flags = 0;
65 if (fieldDesc.GetNRepetitions() > 0)
66 flags |= RNTupleSerializer::kFlagRepetitiveField;
67 if (fieldDesc.IsProjectedField())
68 flags |= RNTupleSerializer::kFlagProjectedField;
69 if (fieldDesc.GetTypeChecksum().has_value())
70 flags |= RNTupleSerializer::kFlagHasTypeChecksum;
71 pos += RNTupleSerializer::SerializeUInt16(flags, *where);
72
73 pos += RNTupleSerializer::SerializeString(fieldDesc.GetFieldName(), *where);
74 pos += RNTupleSerializer::SerializeString(fieldDesc.GetTypeName(), *where);
75 pos += RNTupleSerializer::SerializeString(fieldDesc.GetTypeAlias(), *where);
76 pos += RNTupleSerializer::SerializeString(fieldDesc.GetFieldDescription(), *where);
77
78 if (flags & RNTupleSerializer::kFlagRepetitiveField) {
79 pos += RNTupleSerializer::SerializeUInt64(fieldDesc.GetNRepetitions(), *where);
80 }
81 if (flags & RNTupleSerializer::kFlagProjectedField) {
82 pos += RNTupleSerializer::SerializeUInt32(onDiskProjectionSourceId, *where);
83 }
84 if (flags & RNTupleSerializer::kFlagHasTypeChecksum) {
85 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetTypeChecksum().value(), *where);
86 }
87
88 auto size = pos - base;
89 RNTupleSerializer::SerializeFramePostscript(base, size);
90
91 return size;
92}
93
94// clang-format off
95/// Serialize, in order, fields enumerated in `fieldList` to `buffer`. `firstOnDiskId` specifies the on-disk ID for the
96/// first element in the `fieldList` sequence. Before calling this function `RContext::MapSchema()` should have been
97/// called on `context` in order to map in-memory field IDs to their on-disk counterpart.
98/// \return The number of bytes written to the output buffer; if `buffer` is `nullptr` no data is serialized and the
99/// required buffer size is returned
100// clang-format on
101std::uint32_t SerializeFieldList(const ROOT::Experimental::RNTupleDescriptor &desc,
102 std::span<const ROOT::Experimental::DescriptorId_t> fieldList,
103 std::size_t firstOnDiskId,
105{
107
108 auto base = reinterpret_cast<unsigned char *>(buffer);
109 auto pos = base;
110 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
111
112 auto fieldZeroId = desc.GetFieldZeroId();
113 ROOT::Experimental::DescriptorId_t onDiskFieldId = firstOnDiskId;
114 for (auto fieldId : fieldList) {
115 const auto &f = desc.GetFieldDescriptor(fieldId);
116 auto onDiskParentId =
117 (f.GetParentId() == fieldZeroId) ? onDiskFieldId : context.GetOnDiskFieldId(f.GetParentId());
118 auto onDiskProjectionSourceId =
119 f.IsProjectedField() ? context.GetOnDiskFieldId(f.GetProjectionSourceId()) : kInvalidDescriptorId;
120 pos += SerializeField(f, onDiskParentId, onDiskProjectionSourceId, *where);
121 ++onDiskFieldId;
122 }
123
124 return pos - base;
125}
126
127RResult<std::uint32_t> DeserializeField(const void *buffer, std::uint64_t bufSize,
129{
130 using ENTupleStructure = ROOT::Experimental::ENTupleStructure;
131
132 auto base = reinterpret_cast<const unsigned char *>(buffer);
133 auto bytes = base;
134 std::uint64_t frameSize;
135 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
136 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
137 if (!result)
138 return R__FORWARD_ERROR(result);
139 bytes += result.Unwrap();
140
141 std::uint32_t fieldVersion;
142 std::uint32_t typeVersion;
143 std::uint32_t parentId;
144 // initialize properly for call to SerializeFieldStructure()
145 ENTupleStructure structure{ENTupleStructure::kLeaf};
146 std::uint16_t flags;
147 if (fnFrameSizeLeft() < 3 * sizeof(std::uint32_t) + RNTupleSerializer::SerializeFieldStructure(structure, nullptr) +
148 sizeof(std::uint16_t)) {
149 return R__FAIL("field record frame too short");
150 }
151 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldVersion);
152 bytes += RNTupleSerializer::DeserializeUInt32(bytes, typeVersion);
153 bytes += RNTupleSerializer::DeserializeUInt32(bytes, parentId);
154 result = RNTupleSerializer::DeserializeFieldStructure(bytes, structure);
155 if (!result)
156 return R__FORWARD_ERROR(result);
157 bytes += result.Unwrap();
158 bytes += RNTupleSerializer::DeserializeUInt16(bytes, flags);
159 fieldDesc.FieldVersion(fieldVersion).TypeVersion(typeVersion).ParentId(parentId).Structure(structure);
160
161 std::string fieldName;
162 std::string typeName;
163 std::string aliasName;
164 std::string description;
165 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), fieldName).Unwrap();
166 if (!result)
167 return R__FORWARD_ERROR(result);
168 bytes += result.Unwrap();
169 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), typeName).Unwrap();
170 if (!result)
171 return R__FORWARD_ERROR(result);
172 bytes += result.Unwrap();
173 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), aliasName).Unwrap();
174 if (!result)
175 return R__FORWARD_ERROR(result);
176 bytes += result.Unwrap();
177 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), description).Unwrap();
178 if (!result)
179 return R__FORWARD_ERROR(result);
180 bytes += result.Unwrap();
181 fieldDesc.FieldName(fieldName).TypeName(typeName).TypeAlias(aliasName).FieldDescription(description);
182
183 if (flags & RNTupleSerializer::kFlagRepetitiveField) {
184 if (fnFrameSizeLeft() < sizeof(std::uint64_t))
185 return R__FAIL("field record frame too short");
186 std::uint64_t nRepetitions;
187 bytes += RNTupleSerializer::DeserializeUInt64(bytes, nRepetitions);
188 fieldDesc.NRepetitions(nRepetitions);
189 }
190
191 if (flags & RNTupleSerializer::kFlagProjectedField) {
192 if (fnFrameSizeLeft() < sizeof(std::uint32_t))
193 return R__FAIL("field record frame too short");
194 std::uint32_t projectionSourceId;
195 bytes += RNTupleSerializer::DeserializeUInt32(bytes, projectionSourceId);
196 fieldDesc.ProjectionSourceId(projectionSourceId);
197 }
198
199 if (flags & RNTupleSerializer::kFlagHasTypeChecksum) {
200 if (fnFrameSizeLeft() < sizeof(std::uint32_t))
201 return R__FAIL("field record frame too short");
202 std::uint32_t typeChecksum;
203 bytes += RNTupleSerializer::DeserializeUInt32(bytes, typeChecksum);
204 fieldDesc.TypeChecksum(typeChecksum);
205 }
206
207 return frameSize;
208}
209
210std::uint32_t SerializePhysicalColumn(const ROOT::Experimental::RColumnDescriptor &columnDesc,
212 void *buffer)
213{
214 R__ASSERT(!columnDesc.IsAliasColumn());
215
216 auto base = reinterpret_cast<unsigned char *>(buffer);
217 auto pos = base;
218 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
219
220 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
221
222 pos += RNTupleSerializer::SerializeColumnType(columnDesc.GetType(), *where);
223 pos += RNTupleSerializer::SerializeUInt16(columnDesc.GetBitsOnStorage(), *where);
224 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskFieldId(columnDesc.GetFieldId()), *where);
225 std::uint16_t flags = 0;
226 if (columnDesc.IsDeferredColumn())
227 flags |= RNTupleSerializer::kFlagDeferredColumn;
228 if (columnDesc.GetValueRange().has_value())
229 flags |= RNTupleSerializer::kFlagHasValueRange;
230 std::int64_t firstElementIdx = columnDesc.GetFirstElementIndex();
231 if (columnDesc.IsSuppressedDeferredColumn())
232 firstElementIdx = -firstElementIdx;
233 pos += RNTupleSerializer::SerializeUInt16(flags, *where);
234 pos += RNTupleSerializer::SerializeUInt16(columnDesc.GetRepresentationIndex(), *where);
235 if (flags & RNTupleSerializer::kFlagDeferredColumn)
236 pos += RNTupleSerializer::SerializeInt64(firstElementIdx, *where);
237 if (flags & RNTupleSerializer::kFlagHasValueRange) {
238 auto [min, max] = *columnDesc.GetValueRange();
239 std::uint64_t intMin, intMax;
240 static_assert(sizeof(min) == sizeof(intMin) && sizeof(max) == sizeof(intMax));
241 memcpy(&intMin, &min, sizeof(min));
242 memcpy(&intMax, &max, sizeof(max));
243 pos += RNTupleSerializer::SerializeUInt64(intMin, *where);
244 pos += RNTupleSerializer::SerializeUInt64(intMax, *where);
245 }
246
247 pos += RNTupleSerializer::SerializeFramePostscript(buffer ? base : nullptr, pos - base);
248
249 return pos - base;
250}
251
252std::uint32_t SerializeColumnsOfFields(const ROOT::Experimental::RNTupleDescriptor &desc,
253 std::span<const ROOT::Experimental::DescriptorId_t> fieldList,
255 void *buffer)
256{
257 auto base = reinterpret_cast<unsigned char *>(buffer);
258 auto pos = base;
259 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
260
261 for (auto parentId : fieldList) {
262 for (const auto &c : desc.GetColumnIterable(parentId)) {
263 if (c.IsAliasColumn())
264 continue;
265
266 pos += SerializePhysicalColumn(c, context, *where);
267 }
268 }
269
270 return pos - base;
271}
272
273RResult<std::uint32_t> DeserializeColumn(const void *buffer, std::uint64_t bufSize,
275{
277
278 auto base = reinterpret_cast<const unsigned char *>(buffer);
279 auto bytes = base;
280 std::uint64_t frameSize;
281 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
282 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
283 if (!result)
284 return R__FORWARD_ERROR(result);
285 bytes += result.Unwrap();
286
287 // Initialize properly for SerializeColumnType
288 EColumnType type{EColumnType::kIndex32};
289 std::uint16_t bitsOnStorage;
290 std::uint32_t fieldId;
291 std::uint16_t flags;
292 std::uint16_t representationIndex;
293 std::int64_t firstElementIdx = 0;
294 if (fnFrameSizeLeft() <
295 RNTupleSerializer::SerializeColumnType(type, nullptr) + sizeof(std::uint16_t) + 2 * sizeof(std::uint32_t)) {
296 return R__FAIL("column record frame too short");
297 }
298 result = RNTupleSerializer::DeserializeColumnType(bytes, type);
299 if (!result)
300 return R__FORWARD_ERROR(result);
301 bytes += result.Unwrap();
302 bytes += RNTupleSerializer::DeserializeUInt16(bytes, bitsOnStorage);
303 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldId);
304 bytes += RNTupleSerializer::DeserializeUInt16(bytes, flags);
305 bytes += RNTupleSerializer::DeserializeUInt16(bytes, representationIndex);
306 if (flags & RNTupleSerializer::kFlagDeferredColumn) {
307 if (fnFrameSizeLeft() < sizeof(std::uint64_t))
308 return R__FAIL("column record frame too short");
309 bytes += RNTupleSerializer::DeserializeInt64(bytes, firstElementIdx);
310 }
311 if (flags & RNTupleSerializer::kFlagHasValueRange) {
312 if (fnFrameSizeLeft() < 2 * sizeof(std::uint64_t))
313 return R__FAIL("field record frame too short");
314 std::uint64_t minInt, maxInt;
315 bytes += RNTupleSerializer::DeserializeUInt64(bytes, minInt);
316 bytes += RNTupleSerializer::DeserializeUInt64(bytes, maxInt);
317 double min, max;
318 memcpy(&min, &minInt, sizeof(min));
319 memcpy(&max, &maxInt, sizeof(max));
320 columnDesc.ValueRange(min, max);
321 }
322
323 columnDesc.FieldId(fieldId).BitsOnStorage(bitsOnStorage).Type(type).RepresentationIndex(representationIndex);
324 columnDesc.FirstElementIndex(std::abs(firstElementIdx));
325 if (firstElementIdx < 0)
326 columnDesc.SetSuppressedDeferred();
327
328 return frameSize;
329}
330
331std::uint32_t SerializeExtraTypeInfo(const ROOT::Experimental::RExtraTypeInfoDescriptor &desc, void *buffer)
332{
333 auto base = reinterpret_cast<unsigned char *>(buffer);
334 auto pos = base;
335 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
336
337 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
338
339 pos += RNTupleSerializer::SerializeExtraTypeInfoId(desc.GetContentId(), *where);
340 pos += RNTupleSerializer::SerializeUInt32(desc.GetTypeVersion(), *where);
341 pos += RNTupleSerializer::SerializeString(desc.GetTypeName(), *where);
342 pos += RNTupleSerializer::SerializeString(desc.GetContent(), *where);
343
344 auto size = pos - base;
345 RNTupleSerializer::SerializeFramePostscript(base, size);
346
347 return size;
348}
349
350std::uint32_t SerializeExtraTypeInfoList(const ROOT::Experimental::RNTupleDescriptor &ntplDesc, void *buffer)
351{
352 auto base = reinterpret_cast<unsigned char *>(buffer);
353 auto pos = base;
354 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
355
356 for (const auto &extraTypeInfoDesc : ntplDesc.GetExtraTypeInfoIterable()) {
357 pos += SerializeExtraTypeInfo(extraTypeInfoDesc, *where);
358 }
359
360 return pos - base;
361}
362
363RResult<std::uint32_t> DeserializeExtraTypeInfo(const void *buffer, std::uint64_t bufSize,
365{
367
368 auto base = reinterpret_cast<const unsigned char *>(buffer);
369 auto bytes = base;
370 std::uint64_t frameSize;
371 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
372 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
373 if (!result)
374 return R__FORWARD_ERROR(result);
375 bytes += result.Unwrap();
376
377 EExtraTypeInfoIds contentId{EExtraTypeInfoIds::kInvalid};
378 std::uint32_t typeVersion;
379 if (fnFrameSizeLeft() < 2 * sizeof(std::uint32_t)) {
380 return R__FAIL("extra type info record frame too short");
381 }
382 result = RNTupleSerializer::DeserializeExtraTypeInfoId(bytes, contentId);
383 if (!result)
384 return R__FORWARD_ERROR(result);
385 bytes += result.Unwrap();
386 bytes += RNTupleSerializer::DeserializeUInt32(bytes, typeVersion);
387
388 std::string typeName;
389 std::string content;
390 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), typeName).Unwrap();
391 if (!result)
392 return R__FORWARD_ERROR(result);
393 bytes += result.Unwrap();
394 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), content).Unwrap();
395 if (!result)
396 return R__FORWARD_ERROR(result);
397 bytes += result.Unwrap();
398
399 desc.ContentId(contentId).TypeVersion(typeVersion).TypeName(typeName).Content(content);
400
401 return frameSize;
402}
403
404std::uint32_t SerializeLocatorPayloadLarge(const ROOT::Experimental::RNTupleLocator &locator, unsigned char *buffer)
405{
406 if (buffer) {
407 RNTupleSerializer::SerializeUInt64(locator.fBytesOnStorage, buffer);
408 RNTupleSerializer::SerializeUInt64(locator.GetPosition<std::uint64_t>(), buffer + sizeof(std::uint64_t));
409 }
410 return sizeof(std::uint64_t) + sizeof(std::uint64_t);
411}
412
413void DeserializeLocatorPayloadLarge(const unsigned char *buffer, ROOT::Experimental::RNTupleLocator &locator)
414{
415 auto &data = locator.fPosition.emplace<std::uint64_t>();
416 RNTupleSerializer::DeserializeUInt64(buffer, locator.fBytesOnStorage);
417 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint64_t), data);
418}
419
420std::uint32_t SerializeLocatorPayloadObject64(const ROOT::Experimental::RNTupleLocator &locator, unsigned char *buffer)
421{
423 const uint32_t sizeofBytesOnStorage = (locator.fBytesOnStorage > std::numeric_limits<std::uint32_t>::max())
424 ? sizeof(std::uint64_t)
425 : sizeof(std::uint32_t);
426 if (buffer) {
427 if (sizeofBytesOnStorage == sizeof(std::uint32_t)) {
428 RNTupleSerializer::SerializeUInt32(locator.fBytesOnStorage, buffer);
429 } else {
430 RNTupleSerializer::SerializeUInt64(locator.fBytesOnStorage, buffer);
431 }
432 RNTupleSerializer::SerializeUInt64(data.fLocation, buffer + sizeofBytesOnStorage);
433 }
434 return sizeofBytesOnStorage + sizeof(std::uint64_t);
435}
436
437void DeserializeLocatorPayloadObject64(const unsigned char *buffer, std::uint32_t sizeofLocatorPayload,
439{
441
443 if (sizeofLocatorPayload == 12) {
444 std::uint32_t bytesOnStorage;
445 RNTupleSerializer::DeserializeUInt32(buffer, bytesOnStorage);
446 locator.fBytesOnStorage = bytesOnStorage;
447 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint32_t), data.fLocation);
448 } else if (sizeofLocatorPayload == 16) {
449 RNTupleSerializer::DeserializeUInt64(buffer, locator.fBytesOnStorage);
450 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint64_t), data.fLocation);
451 } else {
452 throw RException(R__FAIL("invalid DAOS locator payload size: " + std::to_string(sizeofLocatorPayload)));
453 }
454}
455
456std::uint32_t SerializeAliasColumn(const ROOT::Experimental::RColumnDescriptor &columnDesc,
458 void *buffer)
459{
460 R__ASSERT(columnDesc.IsAliasColumn());
461
462 auto base = reinterpret_cast<unsigned char *>(buffer);
463 auto pos = base;
464 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
465
466 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
467
468 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskColumnId(columnDesc.GetPhysicalId()), *where);
469 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskFieldId(columnDesc.GetFieldId()), *where);
470
471 pos += RNTupleSerializer::SerializeFramePostscript(buffer ? base : nullptr, pos - base);
472
473 return pos - base;
474}
475
476std::uint32_t SerializeAliasColumnsOfFields(const ROOT::Experimental::RNTupleDescriptor &desc,
477 std::span<const ROOT::Experimental::DescriptorId_t> fieldList,
479 void *buffer)
480{
481 auto base = reinterpret_cast<unsigned char *>(buffer);
482 auto pos = base;
483 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
484
485 for (auto parentId : fieldList) {
486 for (const auto &c : desc.GetColumnIterable(parentId)) {
487 if (!c.IsAliasColumn())
488 continue;
489
490 pos += SerializeAliasColumn(c, context, *where);
491 }
492 }
493
494 return pos - base;
495}
496
497RResult<std::uint32_t> DeserializeAliasColumn(const void *buffer, std::uint64_t bufSize,
498 std::uint32_t &physicalColumnId, std::uint32_t &fieldId)
499{
500 auto base = reinterpret_cast<const unsigned char *>(buffer);
501 auto bytes = base;
502 std::uint64_t frameSize;
503 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
504 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
505 if (!result)
506 return R__FORWARD_ERROR(result);
507 bytes += result.Unwrap();
508
509 if (fnFrameSizeLeft() < 2 * sizeof(std::uint32_t)) {
510 return R__FAIL("alias column record frame too short");
511 }
512
513 bytes += RNTupleSerializer::DeserializeUInt32(bytes, physicalColumnId);
514 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldId);
515
516 return frameSize;
517}
518
519} // anonymous namespace
520
522 std::uint64_t length,
523 std::uint64_t &xxhash3, void *buffer)
524{
525 if (buffer != nullptr) {
526 xxhash3 = XXH3_64bits(data, length);
527 SerializeUInt64(xxhash3, buffer);
528 }
529 return 8;
530}
531
533 std::uint64_t length,
534 std::uint64_t &xxhash3)
535{
536 auto checksumReal = XXH3_64bits(data, length);
537 DeserializeUInt64(data + length, xxhash3);
538 if (xxhash3 != checksumReal)
539 return R__FAIL("XxHash-3 checksum mismatch");
540 return RResult<void>::Success();
541}
542
545{
546 std::uint64_t xxhash3;
547 return R__FORWARD_RESULT(VerifyXxHash3(data, length, xxhash3));
548}
549
550std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeInt16(std::int16_t val, void *buffer)
551{
552 if (buffer != nullptr) {
553 auto bytes = reinterpret_cast<unsigned char *>(buffer);
554 bytes[0] = (val & 0x00FF);
555 bytes[1] = (val & 0xFF00) >> 8;
556 }
557 return 2;
558}
559
560std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeInt16(const void *buffer, std::int16_t &val)
561{
562 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
563 val = std::int16_t(bytes[0]) + (std::int16_t(bytes[1]) << 8);
564 return 2;
565}
566
567std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeUInt16(std::uint16_t val, void *buffer)
568{
569 return SerializeInt16(val, buffer);
570}
571
572std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeUInt16(const void *buffer, std::uint16_t &val)
573{
574 return DeserializeInt16(buffer, *reinterpret_cast<std::int16_t *>(&val));
575}
576
577std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeInt32(std::int32_t val, void *buffer)
578{
579 if (buffer != nullptr) {
580 auto bytes = reinterpret_cast<unsigned char *>(buffer);
581 bytes[0] = (val & 0x000000FF);
582 bytes[1] = (val & 0x0000FF00) >> 8;
583 bytes[2] = (val & 0x00FF0000) >> 16;
584 bytes[3] = (val & 0xFF000000) >> 24;
585 }
586 return 4;
587}
588
589std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeInt32(const void *buffer, std::int32_t &val)
590{
591 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
592 val = std::int32_t(bytes[0]) + (std::int32_t(bytes[1]) << 8) + (std::int32_t(bytes[2]) << 16) +
593 (std::int32_t(bytes[3]) << 24);
594 return 4;
595}
596
597std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeUInt32(std::uint32_t val, void *buffer)
598{
599 return SerializeInt32(val, buffer);
600}
601
602std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeUInt32(const void *buffer, std::uint32_t &val)
603{
604 return DeserializeInt32(buffer, *reinterpret_cast<std::int32_t *>(&val));
605}
606
607std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeInt64(std::int64_t val, void *buffer)
608{
609 if (buffer != nullptr) {
610 auto bytes = reinterpret_cast<unsigned char *>(buffer);
611 bytes[0] = (val & 0x00000000000000FF);
612 bytes[1] = (val & 0x000000000000FF00) >> 8;
613 bytes[2] = (val & 0x0000000000FF0000) >> 16;
614 bytes[3] = (val & 0x00000000FF000000) >> 24;
615 bytes[4] = (val & 0x000000FF00000000) >> 32;
616 bytes[5] = (val & 0x0000FF0000000000) >> 40;
617 bytes[6] = (val & 0x00FF000000000000) >> 48;
618 bytes[7] = (val & 0xFF00000000000000) >> 56;
619 }
620 return 8;
621}
622
623std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeInt64(const void *buffer, std::int64_t &val)
624{
625 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
626 val = std::int64_t(bytes[0]) + (std::int64_t(bytes[1]) << 8) + (std::int64_t(bytes[2]) << 16) +
627 (std::int64_t(bytes[3]) << 24) + (std::int64_t(bytes[4]) << 32) + (std::int64_t(bytes[5]) << 40) +
628 (std::int64_t(bytes[6]) << 48) + (std::int64_t(bytes[7]) << 56);
629 return 8;
630}
631
632std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeUInt64(std::uint64_t val, void *buffer)
633{
634 return SerializeInt64(val, buffer);
635}
636
637std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeUInt64(const void *buffer, std::uint64_t &val)
638{
639 return DeserializeInt64(buffer, *reinterpret_cast<std::int64_t *>(&val));
640}
641
642std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeString(const std::string &val, void *buffer)
643{
644 if (buffer) {
645 auto pos = reinterpret_cast<unsigned char *>(buffer);
646 pos += SerializeUInt32(val.length(), pos);
647 memcpy(pos, val.data(), val.length());
648 }
649 return sizeof(std::uint32_t) + val.length();
650}
651
653 std::uint64_t bufSize,
654 std::string &val)
655{
656 if (bufSize < sizeof(std::uint32_t))
657 return R__FAIL("string buffer too short");
658 bufSize -= sizeof(std::uint32_t);
659
660 auto base = reinterpret_cast<const unsigned char *>(buffer);
661 auto bytes = base;
662 std::uint32_t length;
663 bytes += DeserializeUInt32(buffer, length);
664 if (bufSize < length)
665 return R__FAIL("string buffer too short");
666
667 val.resize(length);
668 memcpy(&val[0], bytes, length);
669 return sizeof(std::uint32_t) + length;
670}
671
672std::uint32_t
674{
676
677 switch (type) {
678 case EColumnType::kBit: return SerializeUInt16(0x00, buffer);
679 case EColumnType::kByte: return SerializeUInt16(0x01, buffer);
680 case EColumnType::kChar: return SerializeUInt16(0x02, buffer);
681 case EColumnType::kInt8: return SerializeUInt16(0x03, buffer);
682 case EColumnType::kUInt8: return SerializeUInt16(0x04, buffer);
683 case EColumnType::kInt16: return SerializeUInt16(0x05, buffer);
684 case EColumnType::kUInt16: return SerializeUInt16(0x06, buffer);
685 case EColumnType::kInt32: return SerializeUInt16(0x07, buffer);
686 case EColumnType::kUInt32: return SerializeUInt16(0x08, buffer);
687 case EColumnType::kInt64: return SerializeUInt16(0x09, buffer);
688 case EColumnType::kUInt64: return SerializeUInt16(0x0A, buffer);
689 case EColumnType::kReal16: return SerializeUInt16(0x0B, buffer);
690 case EColumnType::kReal32: return SerializeUInt16(0x0C, buffer);
691 case EColumnType::kReal64: return SerializeUInt16(0x0D, buffer);
692 case EColumnType::kIndex32: return SerializeUInt16(0x0E, buffer);
693 case EColumnType::kIndex64: return SerializeUInt16(0x0F, buffer);
694 case EColumnType::kSwitch: return SerializeUInt16(0x10, buffer);
695 case EColumnType::kSplitInt16: return SerializeUInt16(0x11, buffer);
696 case EColumnType::kSplitUInt16: return SerializeUInt16(0x12, buffer);
697 case EColumnType::kSplitInt32: return SerializeUInt16(0x13, buffer);
698 case EColumnType::kSplitUInt32: return SerializeUInt16(0x14, buffer);
699 case EColumnType::kSplitInt64: return SerializeUInt16(0x15, buffer);
700 case EColumnType::kSplitUInt64: return SerializeUInt16(0x16, buffer);
701 case EColumnType::kSplitReal32: return SerializeUInt16(0x18, buffer);
702 case EColumnType::kSplitReal64: return SerializeUInt16(0x19, buffer);
703 case EColumnType::kSplitIndex32: return SerializeUInt16(0x1A, buffer);
704 case EColumnType::kSplitIndex64: return SerializeUInt16(0x1B, buffer);
705 case EColumnType::kReal32Trunc: return SerializeUInt16(0x1C, buffer);
706 case EColumnType::kReal32Quant: return SerializeUInt16(0x1D, buffer);
707 default:
708 if (type == kTestFutureType)
709 return SerializeUInt16(0x99, buffer);
710 throw RException(R__FAIL("ROOT bug: unexpected column type"));
711 }
712}
713
717{
719 std::uint16_t onDiskType;
720 auto result = DeserializeUInt16(buffer, onDiskType);
721
722 switch (onDiskType) {
723 case 0x00: type = EColumnType::kBit; break;
724 case 0x01: type = EColumnType::kByte; break;
725 case 0x02: type = EColumnType::kChar; break;
726 case 0x03: type = EColumnType::kInt8; break;
727 case 0x04: type = EColumnType::kUInt8; break;
728 case 0x05: type = EColumnType::kInt16; break;
729 case 0x06: type = EColumnType::kUInt16; break;
730 case 0x07: type = EColumnType::kInt32; break;
731 case 0x08: type = EColumnType::kUInt32; break;
732 case 0x09: type = EColumnType::kInt64; break;
733 case 0x0A: type = EColumnType::kUInt64; break;
734 case 0x0B: type = EColumnType::kReal16; break;
735 case 0x0C: type = EColumnType::kReal32; break;
736 case 0x0D: type = EColumnType::kReal64; break;
737 case 0x0E: type = EColumnType::kIndex32; break;
738 case 0x0F: type = EColumnType::kIndex64; break;
739 case 0x10: type = EColumnType::kSwitch; break;
740 case 0x11: type = EColumnType::kSplitInt16; break;
741 case 0x12: type = EColumnType::kSplitUInt16; break;
742 case 0x13: type = EColumnType::kSplitInt32; break;
743 case 0x14: type = EColumnType::kSplitUInt32; break;
744 case 0x15: type = EColumnType::kSplitInt64; break;
745 case 0x16: type = EColumnType::kSplitUInt64; break;
746 case 0x18: type = EColumnType::kSplitReal32; break;
747 case 0x19: type = EColumnType::kSplitReal64; break;
748 case 0x1A: type = EColumnType::kSplitIndex32; break;
749 case 0x1B: type = EColumnType::kSplitIndex64; break;
750 case 0x1C: type = EColumnType::kReal32Trunc; break;
751 case 0x1D: type = EColumnType::kReal32Quant; break;
752 // case 0x99 => kTestFutureType missing on purpose
753 default:
754 // may be a column type introduced by a future version
756 break;
757 }
758 return result;
759}
760
761std::uint32_t
763 void *buffer)
764{
766 switch (structure) {
767 case ENTupleStructure::kLeaf: return SerializeUInt16(0x00, buffer);
768 case ENTupleStructure::kCollection: return SerializeUInt16(0x01, buffer);
769 case ENTupleStructure::kRecord: return SerializeUInt16(0x02, buffer);
770 case ENTupleStructure::kVariant: return SerializeUInt16(0x03, buffer);
771 case ENTupleStructure::kStreamer: return SerializeUInt16(0x04, buffer);
772 default:
774 return SerializeUInt16(0x99, buffer);
775 throw RException(R__FAIL("ROOT bug: unexpected field structure type"));
776 }
777}
778
780 const void *buffer, ROOT::Experimental::ENTupleStructure &structure)
781{
783 std::uint16_t onDiskValue;
784 auto result = DeserializeUInt16(buffer, onDiskValue);
785 switch (onDiskValue) {
786 case 0x00: structure = ENTupleStructure::kLeaf; break;
787 case 0x01: structure = ENTupleStructure::kCollection; break;
788 case 0x02: structure = ENTupleStructure::kRecord; break;
789 case 0x03: structure = ENTupleStructure::kVariant; break;
790 case 0x04: structure = ENTupleStructure::kStreamer; break;
791 // case 0x99 => kTestFutureFieldStructure intentionally missing
792 default: structure = ENTupleStructure::kUnknown;
793 }
794 return result;
795}
796
797std::uint32_t
799 void *buffer)
800{
802 switch (id) {
803 case EExtraTypeInfoIds::kStreamerInfo: return SerializeUInt32(0x00, buffer);
804 default: throw RException(R__FAIL("ROOT bug: unexpected extra type info id"));
805 }
806}
807
811{
813 std::uint32_t onDiskValue;
814 auto result = DeserializeUInt32(buffer, onDiskValue);
815 switch (onDiskValue) {
816 case 0x00: id = EExtraTypeInfoIds::kStreamerInfo; break;
817 default:
819 R__LOG_DEBUG(0, NTupleLog()) << "Unknown extra type info id: " << onDiskValue;
820 }
821 return result;
822}
823
824std::uint32_t
826{
827 auto base = reinterpret_cast<unsigned char *>(buffer);
828 auto pos = base;
829 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
830
831 pos += SerializeUInt64(envelopeType, *where);
832 // The 48bits size information is filled in the postscript
833 return pos - base;
834}
835
837 std::uint64_t size,
838 std::uint64_t &xxhash3)
839{
840 if (size < sizeof(std::uint64_t))
841 throw RException(R__FAIL("envelope size too small"));
842 if (size >= static_cast<uint64_t>(1) << 48)
843 throw RException(R__FAIL("envelope size too big"));
844 if (envelope) {
845 std::uint64_t typeAndSize;
846 DeserializeUInt64(envelope, typeAndSize);
847 typeAndSize |= (size + 8) << 16;
848 SerializeUInt64(typeAndSize, envelope);
849 }
850 return SerializeXxHash3(envelope, size, xxhash3, envelope ? (envelope + size) : nullptr);
851}
852
854 std::uint64_t size)
855{
856 std::uint64_t xxhash3;
857 return SerializeEnvelopePostscript(envelope, size, xxhash3);
858}
859
862 std::uint16_t expectedType, std::uint64_t &xxhash3)
863{
864 const std::uint64_t minEnvelopeSize = sizeof(std::uint64_t) + sizeof(std::uint64_t);
865 if (bufSize < minEnvelopeSize)
866 return R__FAIL("invalid envelope buffer, too short");
867
868 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
869 auto base = bytes;
870
871 std::uint64_t typeAndSize;
872 bytes += DeserializeUInt64(bytes, typeAndSize);
873
874 std::uint16_t envelopeType = typeAndSize & 0xFFFF;
875 if (envelopeType != expectedType) {
876 return R__FAIL("envelope type mismatch: expected " + std::to_string(expectedType) + ", found " +
877 std::to_string(envelopeType));
878 }
879
880 std::uint64_t envelopeSize = typeAndSize >> 16;
881 if (bufSize < envelopeSize)
882 return R__FAIL("envelope buffer size too small");
883 if (envelopeSize < minEnvelopeSize)
884 return R__FAIL("invalid envelope, too short");
885
886 auto result = VerifyXxHash3(base, envelopeSize - 8, xxhash3);
887 if (!result)
888 return R__FORWARD_ERROR(result);
889
890 return sizeof(typeAndSize);
891}
892
894 std::uint64_t bufSize,
895 std::uint16_t expectedType)
896{
897 std::uint64_t xxhash3;
898 return R__FORWARD_RESULT(DeserializeEnvelope(buffer, bufSize, expectedType, xxhash3));
899}
900
902{
903 // Marker: multiply the final size with 1
904 return SerializeInt64(1, buffer);
905}
906
907std::uint32_t
909{
910 auto base = reinterpret_cast<unsigned char *>(buffer);
911 auto pos = base;
912 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
913
914 // Marker: multiply the final size with -1
915 pos += SerializeInt64(-1, *where);
916 pos += SerializeUInt32(nitems, *where);
917 return pos - base;
918}
919
921{
922 auto preambleSize = sizeof(std::int64_t);
923 if (size < preambleSize)
924 throw RException(R__FAIL("frame too short: " + std::to_string(size)));
925 if (frame) {
926 std::int64_t marker;
927 DeserializeInt64(frame, marker);
928 if ((marker < 0) && (size < (sizeof(std::uint32_t) + preambleSize)))
929 throw RException(R__FAIL("frame too short: " + std::to_string(size)));
930 SerializeInt64(marker * static_cast<int64_t>(size), frame);
931 }
932 return 0;
933}
934
937 std::uint64_t &frameSize, std::uint32_t &nitems)
938{
939 std::uint64_t minSize = sizeof(std::int64_t);
940 if (bufSize < minSize)
941 return R__FAIL("frame too short");
942
943 std::int64_t *ssize = reinterpret_cast<std::int64_t *>(&frameSize);
944 DeserializeInt64(buffer, *ssize);
945
946 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
947 bytes += minSize;
948
949 if (*ssize >= 0) {
950 // Record frame
951 nitems = 1;
952 } else {
953 // List frame
954 minSize += sizeof(std::uint32_t);
955 if (bufSize < minSize)
956 return R__FAIL("frame too short");
957 bytes += DeserializeUInt32(bytes, nitems);
958 *ssize = -(*ssize);
959 }
960
961 if (frameSize < minSize)
962 return R__FAIL("corrupt frame size");
963 if (bufSize < frameSize)
964 return R__FAIL("frame too short");
965
966 return bytes - reinterpret_cast<const unsigned char *>(buffer);
967}
968
971 std::uint64_t &frameSize)
972{
973 std::uint32_t nitems;
974 return R__FORWARD_RESULT(DeserializeFrameHeader(buffer, bufSize, frameSize, nitems));
975}
976
977std::uint32_t
979 void *buffer)
980{
981 if (flags.empty())
982 return SerializeUInt64(0, buffer);
983
984 if (buffer) {
985 auto bytes = reinterpret_cast<unsigned char *>(buffer);
986
987 for (unsigned i = 0; i < flags.size(); ++i) {
988 if (flags[i] & 0x8000000000000000)
989 throw RException(R__FAIL("feature flag out of bounds"));
990
991 // The MSb indicates that another Int64 follows; set this bit to 1 for all except the last element
992 if (i == (flags.size() - 1))
993 SerializeUInt64(flags[i], bytes);
994 else
995 bytes += SerializeUInt64(flags[i] | 0x8000000000000000, bytes);
996 }
997 }
998 return (flags.size() * sizeof(std::int64_t));
999}
1000
1003 std::vector<std::uint64_t> &flags)
1004{
1005 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1006
1007 flags.clear();
1008 std::uint64_t f;
1009 do {
1010 if (bufSize < sizeof(std::uint64_t))
1011 return R__FAIL("feature flag buffer too short");
1012 bytes += DeserializeUInt64(bytes, f);
1013 bufSize -= sizeof(std::uint64_t);
1014 flags.emplace_back(f & ~0x8000000000000000);
1015 } while (f & 0x8000000000000000);
1016
1017 return (flags.size() * sizeof(std::uint64_t));
1018}
1019
1020std::uint32_t
1022{
1024 throw RException(R__FAIL("locator is not serializable"));
1025
1026 std::uint32_t size = 0;
1027 if ((locator.fType == RNTupleLocator::kTypeFile) &&
1028 (locator.fBytesOnStorage <= std::numeric_limits<std::int32_t>::max())) {
1029 size += SerializeUInt32(locator.fBytesOnStorage, buffer);
1030 size += SerializeUInt64(locator.GetPosition<std::uint64_t>(),
1031 buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
1032 return size;
1033 }
1034
1035 std::uint8_t locatorType = 0;
1036 auto payloadp = buffer ? reinterpret_cast<unsigned char *>(buffer) + sizeof(std::int32_t) : nullptr;
1037 switch (locator.fType) {
1039 size += SerializeLocatorPayloadLarge(locator, payloadp);
1040 locatorType = 0x01;
1041 break;
1043 size += SerializeLocatorPayloadObject64(locator, payloadp);
1044 locatorType = 0x02;
1045 break;
1046 default:
1047 if (locator.fType == kTestLocatorType) {
1048 // For the testing locator, use the same payload as Object64. We're not gonna really read it back anyway.
1049 size += SerializeLocatorPayloadObject64(locator, payloadp);
1050 locatorType = 0x7e;
1051 } else {
1052 throw RException(R__FAIL("locator has unknown type"));
1053 }
1054 }
1055 std::int32_t head = sizeof(std::int32_t) + size;
1056 head |= locator.fReserved << 16;
1057 head |= static_cast<int>(locatorType & 0x7F) << 24;
1058 head = -head;
1059 size += RNTupleSerializer::SerializeInt32(head, buffer);
1060 return size;
1061}
1062
1064 std::uint64_t bufSize,
1065 RNTupleLocator &locator)
1066{
1067 if (bufSize < sizeof(std::int32_t))
1068 return R__FAIL("too short locator");
1069
1070 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1071 std::int32_t head;
1072
1073 bytes += DeserializeInt32(bytes, head);
1074 bufSize -= sizeof(std::int32_t);
1075 if (head < 0) {
1076 head = -head;
1077 const int type = head >> 24;
1078 const std::uint32_t payloadSize = (static_cast<std::uint32_t>(head) & 0x0000FFFF) - sizeof(std::int32_t);
1079 if (bufSize < payloadSize)
1080 return R__FAIL("too short locator");
1081
1082 locator.fReserved = static_cast<std::uint32_t>(head >> 16) & 0xFF;
1083 switch (type) {
1084 case 0x01:
1086 DeserializeLocatorPayloadLarge(bytes, locator);
1087 break;
1088 case 0x02:
1090 DeserializeLocatorPayloadObject64(bytes, payloadSize, locator);
1091 break;
1092 default: locator.fType = RNTupleLocator::kTypeUnknown;
1093 }
1094 bytes += payloadSize;
1095 } else {
1096 if (bufSize < sizeof(std::uint64_t))
1097 return R__FAIL("too short locator");
1098 auto &offset = locator.fPosition.emplace<std::uint64_t>();
1100 bytes += DeserializeUInt64(bytes, offset);
1101 locator.fBytesOnStorage = head;
1102 }
1103
1104 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1105}
1106
1107std::uint32_t
1109{
1110 auto size = SerializeUInt64(envelopeLink.fLength, buffer);
1111 size += SerializeLocator(envelopeLink.fLocator, buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
1112 return size;
1113}
1114
1117 REnvelopeLink &envelopeLink)
1118{
1119 if (bufSize < sizeof(std::int64_t))
1120 return R__FAIL("too short envelope link");
1121
1122 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
1123 bytes += DeserializeUInt64(bytes, envelopeLink.fLength);
1124 bufSize -= sizeof(std::uint64_t);
1125 auto result = DeserializeLocator(bytes, bufSize, envelopeLink.fLocator);
1126 if (!result)
1127 return R__FORWARD_ERROR(result);
1128 bytes += result.Unwrap();
1129 return bytes - reinterpret_cast<const unsigned char *>(buffer);
1130}
1131
1132std::uint32_t
1134 void *buffer)
1135{
1136 if (clusterSummary.fNEntries >= (static_cast<std::uint64_t>(1) << 56)) {
1137 throw RException(R__FAIL("number of entries in cluster exceeds maximum of 2^56"));
1138 }
1139
1140 auto base = reinterpret_cast<unsigned char *>(buffer);
1141 auto pos = base;
1142 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1143
1144 auto frame = pos;
1145 pos += SerializeRecordFramePreamble(*where);
1146 pos += SerializeUInt64(clusterSummary.fFirstEntry, *where);
1147 const std::uint64_t nEntriesAndFlags =
1148 (static_cast<std::uint64_t>(clusterSummary.fFlags) << 56) | clusterSummary.fNEntries;
1149 pos += SerializeUInt64(nEntriesAndFlags, *where);
1150
1151 auto size = pos - frame;
1152 pos += SerializeFramePostscript(frame, size);
1153 return size;
1154}
1155
1158 RClusterSummary &clusterSummary)
1159{
1160 auto base = reinterpret_cast<const unsigned char *>(buffer);
1161 auto bytes = base;
1162 std::uint64_t frameSize;
1163 auto result = DeserializeFrameHeader(bytes, bufSize, frameSize);
1164 if (!result)
1165 return R__FORWARD_ERROR(result);
1166 bytes += result.Unwrap();
1167
1168 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
1169 if (fnFrameSizeLeft() < 2 * sizeof(std::uint64_t))
1170 return R__FAIL("too short cluster summary");
1171
1172 bytes += DeserializeUInt64(bytes, clusterSummary.fFirstEntry);
1173 std::uint64_t nEntriesAndFlags;
1174 bytes += DeserializeUInt64(bytes, nEntriesAndFlags);
1175
1176 const std::uint64_t nEntries = (nEntriesAndFlags << 8) >> 8;
1177 const std::uint8_t flags = nEntriesAndFlags >> 56;
1178
1179 if (flags & 0x01) {
1180 return R__FAIL("sharded cluster flag set in cluster summary; sharded clusters are currently unsupported.");
1181 }
1182
1183 clusterSummary.fNEntries = nEntries;
1184 clusterSummary.fFlags = flags;
1185
1186 return frameSize;
1187}
1188
1189std::uint32_t
1191{
1192 auto base = reinterpret_cast<unsigned char *>(buffer);
1193 auto pos = base;
1194 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1195
1196 auto frame = pos;
1197 pos += SerializeRecordFramePreamble(*where);
1198 pos += SerializeUInt64(clusterGroup.fMinEntry, *where);
1199 pos += SerializeUInt64(clusterGroup.fEntrySpan, *where);
1200 pos += SerializeUInt32(clusterGroup.fNClusters, *where);
1201 pos += SerializeEnvelopeLink(clusterGroup.fPageListEnvelopeLink, *where);
1202 auto size = pos - frame;
1203 pos += SerializeFramePostscript(frame, size);
1204 return size;
1205}
1206
1209 RClusterGroup &clusterGroup)
1210{
1211 auto base = reinterpret_cast<const unsigned char *>(buffer);
1212 auto bytes = base;
1213
1214 std::uint64_t frameSize;
1215 auto result = DeserializeFrameHeader(bytes, bufSize, frameSize);
1216 if (!result)
1217 return R__FORWARD_ERROR(result);
1218 bytes += result.Unwrap();
1219
1220 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - base); };
1221 if (fnFrameSizeLeft() < sizeof(std::uint32_t) + 2 * sizeof(std::uint64_t))
1222 return R__FAIL("too short cluster group");
1223
1224 bytes += DeserializeUInt64(bytes, clusterGroup.fMinEntry);
1225 bytes += DeserializeUInt64(bytes, clusterGroup.fEntrySpan);
1226 bytes += DeserializeUInt32(bytes, clusterGroup.fNClusters);
1227 result = DeserializeEnvelopeLink(bytes, fnFrameSizeLeft(), clusterGroup.fPageListEnvelopeLink);
1228 if (!result)
1229 return R__FORWARD_ERROR(result);
1230
1231 return frameSize;
1232}
1233
1235 bool forHeaderExtension)
1236{
1237 auto fieldZeroId = desc.GetFieldZeroId();
1238 auto depthFirstTraversal = [&](std::span<DescriptorId_t> fieldTrees, auto doForEachField) {
1239 std::deque<DescriptorId_t> idQueue{fieldTrees.begin(), fieldTrees.end()};
1240 while (!idQueue.empty()) {
1241 auto fieldId = idQueue.front();
1242 idQueue.pop_front();
1243 // Field zero has no physical representation nor columns of its own; recurse over its subfields only
1244 if (fieldId != fieldZeroId)
1245 doForEachField(fieldId);
1246 unsigned i = 0;
1247 for (const auto &f : desc.GetFieldIterable(fieldId))
1248 idQueue.insert(idQueue.begin() + i++, f.GetId());
1249 }
1250 };
1251
1252 R__ASSERT(desc.GetNFields() > 0); // we must have at least a zero field
1253 if (!forHeaderExtension)
1254 R__ASSERT(GetHeaderExtensionOffset() == -1U);
1255
1256 std::vector<DescriptorId_t> fieldTrees;
1257 if (!forHeaderExtension) {
1258 fieldTrees.emplace_back(fieldZeroId);
1259 } else if (auto xHeader = desc.GetHeaderExtension()) {
1260 fieldTrees = xHeader->GetTopLevelFields(desc);
1261 }
1262 depthFirstTraversal(fieldTrees, [&](DescriptorId_t fieldId) { MapFieldId(fieldId); });
1263 depthFirstTraversal(fieldTrees, [&](DescriptorId_t fieldId) {
1264 for (const auto &c : desc.GetColumnIterable(fieldId)) {
1265 if (!c.IsAliasColumn()) {
1266 MapPhysicalColumnId(c.GetPhysicalId());
1267 }
1268 }
1269 });
1270
1271 if (forHeaderExtension) {
1272 // Create physical IDs for column representations that extend fields of the regular header.
1273 // First the physical columns then the alias columns.
1274 for (auto memId : desc.GetHeaderExtension()->GetExtendedColumnRepresentations()) {
1275 const auto &columnDesc = desc.GetColumnDescriptor(memId);
1276 if (!columnDesc.IsAliasColumn()) {
1277 MapPhysicalColumnId(columnDesc.GetPhysicalId());
1278 }
1279 }
1280 } else {
1281 // Anything added after this point is accounted for the header extension
1282 BeginHeaderExtension();
1283 }
1284}
1285
1287 const RNTupleDescriptor &desc,
1288 const RContext &context,
1289 bool forHeaderExtension)
1290{
1291 auto base = reinterpret_cast<unsigned char *>(buffer);
1292 auto pos = base;
1293 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1294
1295 std::size_t nFields = 0, nColumns = 0, nAliasColumns = 0, fieldListOffset = 0;
1296 // Columns in the extension header that are attached to a field of the regular header
1297 std::vector<std::reference_wrapper<const RColumnDescriptor>> extraColumns;
1298 if (forHeaderExtension) {
1299 // A call to `RNTupleDescriptorBuilder::BeginHeaderExtension()` is not strictly required after serializing the
1300 // header, which may happen, e.g., in unit tests. Ensure an empty schema extension is serialized in this case
1301 if (auto xHeader = desc.GetHeaderExtension()) {
1302 nFields = xHeader->GetNFields();
1303 nColumns = xHeader->GetNPhysicalColumns();
1304 nAliasColumns = xHeader->GetNLogicalColumns() - xHeader->GetNPhysicalColumns();
1305 fieldListOffset = context.GetHeaderExtensionOffset();
1306
1307 extraColumns.reserve(xHeader->GetExtendedColumnRepresentations().size());
1308 for (auto columnId : xHeader->GetExtendedColumnRepresentations()) {
1309 extraColumns.emplace_back(desc.GetColumnDescriptor(columnId));
1310 }
1311 }
1312 } else {
1313 nFields = desc.GetNFields() - 1;
1314 nColumns = desc.GetNPhysicalColumns();
1315 nAliasColumns = desc.GetNLogicalColumns() - desc.GetNPhysicalColumns();
1316 }
1317 const auto nExtraTypeInfos = desc.GetNExtraTypeInfos();
1318 const auto &onDiskFields = context.GetOnDiskFieldList();
1319 R__ASSERT(onDiskFields.size() >= fieldListOffset);
1320 std::span<const DescriptorId_t> fieldList{onDiskFields.data() + fieldListOffset,
1321 onDiskFields.size() - fieldListOffset};
1322
1323 auto frame = pos;
1324 pos += SerializeListFramePreamble(nFields, *where);
1325 pos += SerializeFieldList(desc, fieldList, /*firstOnDiskId=*/fieldListOffset, context, *where);
1326 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1327
1328 frame = pos;
1329 pos += SerializeListFramePreamble(nColumns, *where);
1330 pos += SerializeColumnsOfFields(desc, fieldList, context, *where);
1331 for (const auto &c : extraColumns) {
1332 if (!c.get().IsAliasColumn()) {
1333 pos += SerializePhysicalColumn(c.get(), context, *where);
1334 }
1335 }
1336 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1337
1338 frame = pos;
1339 pos += SerializeListFramePreamble(nAliasColumns, *where);
1340 pos += SerializeAliasColumnsOfFields(desc, fieldList, context, *where);
1341 for (const auto &c : extraColumns) {
1342 if (c.get().IsAliasColumn()) {
1343 pos += SerializeAliasColumn(c.get(), context, *where);
1344 }
1345 }
1346 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1347
1348 frame = pos;
1349 pos += SerializeListFramePreamble(nExtraTypeInfos, *where);
1350 pos += SerializeExtraTypeInfoList(desc, *where);
1351 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1352
1353 return static_cast<std::uint32_t>(pos - base);
1354}
1355
1358 RNTupleDescriptorBuilder &descBuilder)
1359{
1360 auto base = reinterpret_cast<const unsigned char *>(buffer);
1361 auto bytes = base;
1362 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1364
1365 std::uint64_t frameSize;
1366 auto frame = bytes;
1367 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
1368
1369 std::uint32_t nFields;
1370 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nFields);
1371 if (!result)
1372 return R__FORWARD_ERROR(result);
1373 bytes += result.Unwrap();
1374 // The zero field is always added before `DeserializeSchemaDescription()` is called
1375 const std::uint32_t fieldIdRangeBegin = descBuilder.GetDescriptor().GetNFields() - 1;
1376 for (unsigned i = 0; i < nFields; ++i) {
1377 std::uint32_t fieldId = fieldIdRangeBegin + i;
1378 RFieldDescriptorBuilder fieldBuilder;
1379 result = DeserializeField(bytes, fnFrameSizeLeft(), fieldBuilder);
1380 if (!result)
1381 return R__FORWARD_ERROR(result);
1382 bytes += result.Unwrap();
1383 if (fieldId == fieldBuilder.GetParentId())
1384 fieldBuilder.ParentId(kZeroFieldId);
1385 auto fieldDesc = fieldBuilder.FieldId(fieldId).MakeDescriptor();
1386 if (!fieldDesc)
1387 return R__FORWARD_ERROR(fieldDesc);
1388 const auto parentId = fieldDesc.Inspect().GetParentId();
1389 const auto projectionSourceId = fieldDesc.Inspect().GetProjectionSourceId();
1390 descBuilder.AddField(fieldDesc.Unwrap());
1391 auto resVoid = descBuilder.AddFieldLink(parentId, fieldId);
1392 if (!resVoid)
1393 return R__FORWARD_ERROR(resVoid);
1394 if (projectionSourceId != kInvalidDescriptorId) {
1395 resVoid = descBuilder.AddFieldProjection(projectionSourceId, fieldId);
1396 if (!resVoid)
1397 return R__FORWARD_ERROR(resVoid);
1398 }
1399 }
1400 bytes = frame + frameSize;
1401
1402 // As columns are added in order of representation index and column index, determine the column index
1403 // for the currently deserialized column from the columns already added.
1404 auto fnNextColumnIndex = [&descBuilder](DescriptorId_t fieldId, std::uint16_t representationIndex) -> std::uint32_t {
1405 const auto &existingColumns = descBuilder.GetDescriptor().GetFieldDescriptor(fieldId).GetLogicalColumnIds();
1406 if (existingColumns.empty())
1407 return 0;
1408 const auto &lastColumnDesc = descBuilder.GetDescriptor().GetColumnDescriptor(existingColumns.back());
1409 return (representationIndex == lastColumnDesc.GetRepresentationIndex()) ? (lastColumnDesc.GetIndex() + 1) : 0;
1410 };
1411
1412 std::uint32_t nColumns;
1413 frame = bytes;
1414 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nColumns);
1415 if (!result)
1416 return R__FORWARD_ERROR(result);
1417 bytes += result.Unwrap();
1418
1419 if (descBuilder.GetDescriptor().GetNLogicalColumns() > descBuilder.GetDescriptor().GetNPhysicalColumns())
1420 descBuilder.ShiftAliasColumns(nColumns);
1421
1422 const std::uint32_t columnIdRangeBegin = descBuilder.GetDescriptor().GetNPhysicalColumns();
1423 for (unsigned i = 0; i < nColumns; ++i) {
1424 std::uint32_t columnId = columnIdRangeBegin + i;
1425 RColumnDescriptorBuilder columnBuilder;
1426 result = DeserializeColumn(bytes, fnFrameSizeLeft(), columnBuilder);
1427 if (!result)
1428 return R__FORWARD_ERROR(result);
1429 bytes += result.Unwrap();
1430
1431 columnBuilder.Index(fnNextColumnIndex(columnBuilder.GetFieldId(), columnBuilder.GetRepresentationIndex()));
1432 columnBuilder.LogicalColumnId(columnId);
1433 columnBuilder.PhysicalColumnId(columnId);
1434 auto columnDesc = columnBuilder.MakeDescriptor();
1435 if (!columnDesc)
1436 return R__FORWARD_ERROR(columnDesc);
1437 auto resVoid = descBuilder.AddColumn(columnDesc.Unwrap());
1438 if (!resVoid)
1439 return R__FORWARD_ERROR(resVoid);
1440 }
1441 bytes = frame + frameSize;
1442
1443 std::uint32_t nAliasColumns;
1444 frame = bytes;
1445 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nAliasColumns);
1446 if (!result)
1447 return R__FORWARD_ERROR(result);
1448 bytes += result.Unwrap();
1449 const std::uint32_t aliasColumnIdRangeBegin = descBuilder.GetDescriptor().GetNLogicalColumns();
1450 for (unsigned i = 0; i < nAliasColumns; ++i) {
1451 std::uint32_t physicalId;
1452 std::uint32_t fieldId;
1453 result = DeserializeAliasColumn(bytes, fnFrameSizeLeft(), physicalId, fieldId);
1454 if (!result)
1455 return R__FORWARD_ERROR(result);
1456 bytes += result.Unwrap();
1457
1458 RColumnDescriptorBuilder columnBuilder;
1459 columnBuilder.LogicalColumnId(aliasColumnIdRangeBegin + i).PhysicalColumnId(physicalId).FieldId(fieldId);
1460 const auto &physicalColumnDesc = descBuilder.GetDescriptor().GetColumnDescriptor(physicalId);
1461 columnBuilder.BitsOnStorage(physicalColumnDesc.GetBitsOnStorage());
1462 columnBuilder.ValueRange(physicalColumnDesc.GetValueRange());
1463 columnBuilder.Type(physicalColumnDesc.GetType());
1464 columnBuilder.RepresentationIndex(physicalColumnDesc.GetRepresentationIndex());
1465 columnBuilder.Index(fnNextColumnIndex(columnBuilder.GetFieldId(), columnBuilder.GetRepresentationIndex()));
1466
1467 auto aliasColumnDesc = columnBuilder.MakeDescriptor();
1468 if (!aliasColumnDesc)
1469 return R__FORWARD_ERROR(aliasColumnDesc);
1470 auto resVoid = descBuilder.AddColumn(aliasColumnDesc.Unwrap());
1471 if (!resVoid)
1472 return R__FORWARD_ERROR(resVoid);
1473 }
1474 bytes = frame + frameSize;
1475
1476 std::uint32_t nExtraTypeInfos;
1477 frame = bytes;
1478 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nExtraTypeInfos);
1479 if (!result)
1480 return R__FORWARD_ERROR(result);
1481 bytes += result.Unwrap();
1482 for (unsigned i = 0; i < nExtraTypeInfos; ++i) {
1483 RExtraTypeInfoDescriptorBuilder extraTypeInfoBuilder;
1484 result = DeserializeExtraTypeInfo(bytes, fnFrameSizeLeft(), extraTypeInfoBuilder);
1485 if (!result)
1486 return R__FORWARD_ERROR(result);
1487 bytes += result.Unwrap();
1488
1489 auto extraTypeInfoDesc = extraTypeInfoBuilder.MoveDescriptor();
1490 // We ignore unknown extra type information
1491 if (extraTypeInfoDesc)
1492 descBuilder.AddExtraTypeInfo(extraTypeInfoDesc.Unwrap());
1493 }
1494 bytes = frame + frameSize;
1495
1496 return bytes - base;
1497}
1498
1502{
1503 RContext context;
1504
1505 auto base = reinterpret_cast<unsigned char *>(buffer);
1506 auto pos = base;
1507 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1508
1509 pos += SerializeEnvelopePreamble(kEnvelopeTypeHeader, *where);
1510 // So far we don't make use of feature flags
1511 pos += SerializeFeatureFlags(desc.GetFeatureFlags(), *where);
1512 pos += SerializeString(desc.GetName(), *where);
1513 pos += SerializeString(desc.GetDescription(), *where);
1514 pos += SerializeString(std::string("ROOT v") + ROOT_RELEASE, *where);
1515
1516 context.MapSchema(desc, /*forHeaderExtension=*/false);
1517 pos += SerializeSchemaDescription(*where, desc, context);
1518
1519 std::uint64_t size = pos - base;
1520 std::uint64_t xxhash3 = 0;
1521 size += SerializeEnvelopePostscript(base, size, xxhash3);
1522
1523 context.SetHeaderSize(size);
1524 context.SetHeaderXxHash3(xxhash3);
1525 return context;
1526}
1527
1528std::uint32_t
1530 std::span<DescriptorId_t> physClusterIDs,
1531 const RContext &context)
1532{
1533 auto base = reinterpret_cast<unsigned char *>(buffer);
1534 auto pos = base;
1535 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1536
1537 pos += SerializeEnvelopePreamble(kEnvelopeTypePageList, *where);
1538
1539 pos += SerializeUInt64(context.GetHeaderXxHash3(), *where);
1540
1541 // Cluster summaries
1542 const auto nClusters = physClusterIDs.size();
1543 auto clusterSummaryFrame = pos;
1544 pos += SerializeListFramePreamble(nClusters, *where);
1545 for (auto clusterId : physClusterIDs) {
1546 const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1547 RClusterSummary summary{clusterDesc.GetFirstEntryIndex(), clusterDesc.GetNEntries(), 0};
1548 pos += SerializeClusterSummary(summary, *where);
1549 }
1550 pos += SerializeFramePostscript(buffer ? clusterSummaryFrame : nullptr, pos - clusterSummaryFrame);
1551
1552 // Page locations
1553 auto topMostFrame = pos;
1554 pos += SerializeListFramePreamble(nClusters, *where);
1555
1556 for (auto clusterId : physClusterIDs) {
1557 const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1558 // Get an ordered set of physical column ids
1559 std::set<DescriptorId_t> onDiskColumnIds;
1560 for (const auto &columnRange : clusterDesc.GetColumnRangeIterable())
1561 onDiskColumnIds.insert(context.GetOnDiskColumnId(columnRange.fPhysicalColumnId));
1562
1563 auto outerFrame = pos;
1564 pos += SerializeListFramePreamble(onDiskColumnIds.size(), *where);
1565 for (auto onDiskId : onDiskColumnIds) {
1566 auto memId = context.GetMemColumnId(onDiskId);
1567 const auto &columnRange = clusterDesc.GetColumnRange(memId);
1568
1569 auto innerFrame = pos;
1570 if (columnRange.fIsSuppressed) {
1571 // Empty page range
1572 pos += SerializeListFramePreamble(0, *where);
1573 pos += SerializeInt64(kSuppressedColumnMarker, *where);
1574 } else {
1575 const auto &pageRange = clusterDesc.GetPageRange(memId);
1576 pos += SerializeListFramePreamble(pageRange.fPageInfos.size(), *where);
1577
1578 for (const auto &pi : pageRange.fPageInfos) {
1579 std::int32_t nElements = pi.fHasChecksum ? -static_cast<std::int32_t>(pi.fNElements) : pi.fNElements;
1580 pos += SerializeUInt32(nElements, *where);
1581 pos += SerializeLocator(pi.fLocator, *where);
1582 }
1583 pos += SerializeInt64(columnRange.fFirstElementIndex, *where);
1584 pos += SerializeUInt32(columnRange.fCompressionSettings, *where);
1585 }
1586
1587 pos += SerializeFramePostscript(buffer ? innerFrame : nullptr, pos - innerFrame);
1588 }
1589 pos += SerializeFramePostscript(buffer ? outerFrame : nullptr, pos - outerFrame);
1590 }
1591
1592 pos += SerializeFramePostscript(buffer ? topMostFrame : nullptr, pos - topMostFrame);
1593 std::uint64_t size = pos - base;
1594 size += SerializeEnvelopePostscript(base, size);
1595 return size;
1596}
1597
1598std::uint32_t
1601 const RContext &context)
1602{
1603 auto base = reinterpret_cast<unsigned char *>(buffer);
1604 auto pos = base;
1605 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1606
1607 pos += SerializeEnvelopePreamble(kEnvelopeTypeFooter, *where);
1608
1609 // So far we don't make use of footer feature flags
1610 pos += SerializeFeatureFlags(std::vector<std::uint64_t>(), *where);
1611 pos += SerializeUInt64(context.GetHeaderXxHash3(), *where);
1612
1613 // Schema extension, i.e. incremental changes with respect to the header
1614 auto frame = pos;
1615 pos += SerializeRecordFramePreamble(*where);
1616 pos += SerializeSchemaDescription(*where, desc, context, /*forHeaderExtension=*/true);
1617 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1618
1619 // Cluster groups
1620 frame = pos;
1621 const auto nClusterGroups = desc.GetNClusterGroups();
1622 pos += SerializeListFramePreamble(nClusterGroups, *where);
1623 for (unsigned int i = 0; i < nClusterGroups; ++i) {
1624 const auto &cgDesc = desc.GetClusterGroupDescriptor(context.GetMemClusterGroupId(i));
1625 RClusterGroup clusterGroup;
1626 clusterGroup.fMinEntry = cgDesc.GetMinEntry();
1627 clusterGroup.fEntrySpan = cgDesc.GetEntrySpan();
1628 clusterGroup.fNClusters = cgDesc.GetNClusters();
1629 clusterGroup.fPageListEnvelopeLink.fLength = cgDesc.GetPageListLength();
1630 clusterGroup.fPageListEnvelopeLink.fLocator = cgDesc.GetPageListLocator();
1631 pos += SerializeClusterGroup(clusterGroup, *where);
1632 }
1633 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1634
1635 std::uint32_t size = pos - base;
1636 size += SerializeEnvelopePostscript(base, size);
1637 return size;
1638}
1639
1642 RNTupleDescriptorBuilder &descBuilder)
1643{
1644 auto base = reinterpret_cast<const unsigned char *>(buffer);
1645 auto bytes = base;
1646 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1648
1649 std::uint64_t xxhash3{0};
1650 result = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypeHeader, xxhash3);
1651 if (!result)
1652 return R__FORWARD_ERROR(result);
1653 bytes += result.Unwrap();
1654 descBuilder.SetOnDiskHeaderXxHash3(xxhash3);
1655
1656 std::vector<std::uint64_t> featureFlags;
1657 result = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags);
1658 if (!result)
1659 return R__FORWARD_ERROR(result);
1660 bytes += result.Unwrap();
1661 for (std::size_t i = 0; i < featureFlags.size(); ++i) {
1662 if (!featureFlags[i])
1663 continue;
1664 unsigned int bit = 0;
1665 while (!(featureFlags[i] & (static_cast<uint64_t>(1) << bit)))
1666 bit++;
1667 return R__FAIL("unsupported format feature: " + std::to_string(i * 64 + bit));
1668 }
1669
1670 std::string name;
1671 std::string description;
1672 std::string writer;
1673 result = DeserializeString(bytes, fnBufSizeLeft(), name);
1674 if (!result)
1675 return R__FORWARD_ERROR(result);
1676 bytes += result.Unwrap();
1677 result = DeserializeString(bytes, fnBufSizeLeft(), description);
1678 if (!result)
1679 return R__FORWARD_ERROR(result);
1680 bytes += result.Unwrap();
1681 result = DeserializeString(bytes, fnBufSizeLeft(), writer);
1682 if (!result)
1683 return R__FORWARD_ERROR(result);
1684 bytes += result.Unwrap();
1685 descBuilder.SetNTuple(name, description);
1686
1687 // Zero field
1688 descBuilder.AddField(
1689 RFieldDescriptorBuilder().FieldId(kZeroFieldId).Structure(ENTupleStructure::kRecord).MakeDescriptor().Unwrap());
1690 result = DeserializeSchemaDescription(bytes, fnBufSizeLeft(), descBuilder);
1691 if (!result)
1692 return R__FORWARD_ERROR(result);
1693
1694 return RResult<void>::Success();
1695}
1696
1699 RNTupleDescriptorBuilder &descBuilder)
1700{
1701 auto base = reinterpret_cast<const unsigned char *>(buffer);
1702 auto bytes = base;
1703 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1705
1706 result = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypeFooter);
1707 if (!result)
1708 return R__FORWARD_ERROR(result);
1709 bytes += result.Unwrap();
1710
1711 std::vector<std::uint64_t> featureFlags;
1712 result = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags);
1713 if (!result)
1714 return R__FORWARD_ERROR(result);
1715 bytes += result.Unwrap();
1716 for (auto f : featureFlags) {
1717 if (f)
1718 R__LOG_WARNING(NTupleLog()) << "Unsupported feature flag! " << f;
1719 }
1720
1721 std::uint64_t xxhash3{0};
1722 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
1723 return R__FAIL("footer too short");
1724 bytes += DeserializeUInt64(bytes, xxhash3);
1725 if (xxhash3 != descBuilder.GetDescriptor().GetOnDiskHeaderXxHash3())
1726 return R__FAIL("XxHash-3 mismatch between header and footer");
1727
1728 std::uint64_t frameSize;
1729 auto frame = bytes;
1730 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
1731
1732 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize);
1733 if (!result)
1734 return R__FORWARD_ERROR(result);
1735 bytes += result.Unwrap();
1736 if (fnFrameSizeLeft() > 0) {
1737 descBuilder.BeginHeaderExtension();
1738 result = DeserializeSchemaDescription(bytes, fnFrameSizeLeft(), descBuilder);
1739 if (!result)
1740 return R__FORWARD_ERROR(result);
1741 }
1742 bytes = frame + frameSize;
1743
1744 std::uint32_t nClusterGroups;
1745 frame = bytes;
1746 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nClusterGroups);
1747 if (!result)
1748 return R__FORWARD_ERROR(result);
1749 bytes += result.Unwrap();
1750 for (std::uint32_t groupId = 0; groupId < nClusterGroups; ++groupId) {
1751 RClusterGroup clusterGroup;
1752 result = DeserializeClusterGroup(bytes, fnFrameSizeLeft(), clusterGroup);
1753 if (!result)
1754 return R__FORWARD_ERROR(result);
1755 bytes += result.Unwrap();
1756
1758 RClusterGroupDescriptorBuilder clusterGroupBuilder;
1759 clusterGroupBuilder.ClusterGroupId(groupId)
1762 .MinEntry(clusterGroup.fMinEntry)
1763 .EntrySpan(clusterGroup.fEntrySpan)
1764 .NClusters(clusterGroup.fNClusters);
1765 descBuilder.AddClusterGroup(clusterGroupBuilder.MoveDescriptor().Unwrap());
1766 }
1767 bytes = frame + frameSize;
1768
1769 return RResult<void>::Success();
1770}
1771
1774 DescriptorId_t clusterGroupId,
1775 RNTupleDescriptor &desc)
1776{
1777 auto base = reinterpret_cast<const unsigned char *>(buffer);
1778 auto bytes = base;
1779 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1781
1782 result = DeserializeEnvelope(bytes, fnBufSizeLeft(), kEnvelopeTypePageList);
1783 if (!result)
1784 return R__FORWARD_ERROR(result);
1785 bytes += result.Unwrap();
1786
1787 std::uint64_t xxhash3{0};
1788 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint64_t)))
1789 return R__FAIL("page list too short");
1790 bytes += DeserializeUInt64(bytes, xxhash3);
1791 if (xxhash3 != desc.GetOnDiskHeaderXxHash3())
1792 return R__FAIL("XxHash-3 mismatch between header and page list");
1793
1794 std::vector<RClusterDescriptorBuilder> clusterBuilders;
1795 DescriptorId_t firstClusterId{0};
1796 for (DescriptorId_t i = 0; i < clusterGroupId; ++i) {
1797 firstClusterId = firstClusterId + desc.GetClusterGroupDescriptor(i).GetNClusters();
1798 }
1799
1800 std::uint64_t clusterSummaryFrameSize;
1801 auto clusterSummaryFrame = bytes;
1802 auto fnClusterSummaryFrameSizeLeft = [&]() { return clusterSummaryFrameSize - (bytes - clusterSummaryFrame); };
1803
1804 std::uint32_t nClusterSummaries;
1805 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), clusterSummaryFrameSize, nClusterSummaries);
1806 if (!result)
1807 return R__FORWARD_ERROR(result);
1808 bytes += result.Unwrap();
1809 for (auto clusterId = firstClusterId; clusterId < firstClusterId + nClusterSummaries; ++clusterId) {
1810 RClusterSummary clusterSummary;
1811 result = DeserializeClusterSummary(bytes, fnClusterSummaryFrameSizeLeft(), clusterSummary);
1812 if (!result)
1813 return R__FORWARD_ERROR(result);
1814 bytes += result.Unwrap();
1815
1817 builder.ClusterId(clusterId).FirstEntryIndex(clusterSummary.fFirstEntry).NEntries(clusterSummary.fNEntries);
1818 clusterBuilders.emplace_back(std::move(builder));
1819 }
1820 bytes = clusterSummaryFrame + clusterSummaryFrameSize;
1821
1822 std::uint64_t topMostFrameSize;
1823 auto topMostFrame = bytes;
1824 auto fnTopMostFrameSizeLeft = [&]() { return topMostFrameSize - (bytes - topMostFrame); };
1825
1826 std::uint32_t nClusters;
1827 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), topMostFrameSize, nClusters);
1828 if (!result)
1829 return R__FORWARD_ERROR(result);
1830 bytes += result.Unwrap();
1831
1832 if (nClusters != nClusterSummaries)
1833 return R__FAIL("mismatch between number of clusters and number of cluster summaries");
1834
1835 std::vector<RClusterDescriptor> clusters;
1836 for (std::uint32_t i = 0; i < nClusters; ++i) {
1837 std::uint64_t outerFrameSize;
1838 auto outerFrame = bytes;
1839 auto fnOuterFrameSizeLeft = [&]() { return outerFrameSize - (bytes - outerFrame); };
1840
1841 std::uint32_t nColumns;
1842 result = DeserializeFrameHeader(bytes, fnTopMostFrameSizeLeft(), outerFrameSize, nColumns);
1843 if (!result)
1844 return R__FORWARD_ERROR(result);
1845 bytes += result.Unwrap();
1846
1847 for (std::uint32_t j = 0; j < nColumns; ++j) {
1848 std::uint64_t innerFrameSize;
1849 auto innerFrame = bytes;
1850 auto fnInnerFrameSizeLeft = [&]() { return innerFrameSize - (bytes - innerFrame); };
1851
1852 std::uint32_t nPages;
1853 result = DeserializeFrameHeader(bytes, fnOuterFrameSizeLeft(), innerFrameSize, nPages);
1854 if (!result)
1855 return R__FORWARD_ERROR(result);
1856 bytes += result.Unwrap();
1857
1859 pageRange.fPhysicalColumnId = j;
1860 for (std::uint32_t k = 0; k < nPages; ++k) {
1861 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
1862 return R__FAIL("inner frame too short");
1863 std::int32_t nElements;
1864 bool hasChecksum = false;
1865 RNTupleLocator locator;
1866 bytes += DeserializeInt32(bytes, nElements);
1867 if (nElements < 0) {
1868 nElements = -nElements;
1869 hasChecksum = true;
1870 }
1871 result = DeserializeLocator(bytes, fnInnerFrameSizeLeft(), locator);
1872 if (!result)
1873 return R__FORWARD_ERROR(result);
1874 pageRange.fPageInfos.push_back({static_cast<std::uint32_t>(nElements), locator, hasChecksum});
1875 bytes += result.Unwrap();
1876 }
1877
1878 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::int64_t)))
1879 return R__FAIL("page list frame too short");
1880 std::int64_t columnOffset;
1881 bytes += DeserializeInt64(bytes, columnOffset);
1882 if (columnOffset < 0) {
1883 if (nPages > 0)
1884 return R__FAIL("unexpected non-empty page list");
1885 clusterBuilders[i].MarkSuppressedColumnRange(j);
1886 } else {
1887 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
1888 return R__FAIL("page list frame too short");
1889 std::uint32_t compressionSettings;
1890 bytes += DeserializeUInt32(bytes, compressionSettings);
1891 clusterBuilders[i].CommitColumnRange(j, columnOffset, compressionSettings, pageRange);
1892 }
1893
1894 bytes = innerFrame + innerFrameSize;
1895 } // loop over columns
1896
1897 bytes = outerFrame + outerFrameSize;
1898
1899 auto voidRes = clusterBuilders[i].CommitSuppressedColumnRanges(desc);
1900 if (!voidRes)
1901 return R__FORWARD_ERROR(voidRes);
1902 clusterBuilders[i].AddExtendedColumnRanges(desc);
1903 clusters.emplace_back(clusterBuilders[i].MoveDescriptor().Unwrap());
1904 } // loop over clusters
1905 desc.AddClusterGroupDetails(clusterGroupId, clusters);
1906
1907 return RResult<void>::Success();
1908}
1909
1911{
1912 TList streamerInfos;
1913 for (auto si : infos) {
1914 assert(si.first == si.second->GetNumber());
1915 streamerInfos.Add(si.second);
1916 }
1918 buffer.WriteObject(&streamerInfos);
1919 assert(buffer.Length() > 0);
1920 return std::string{buffer.Buffer(), static_cast<UInt_t>(buffer.Length())};
1921}
1922
1925{
1926 StreamerInfoMap_t infoMap;
1927
1928 TBufferFile buffer(TBuffer::kRead, extraTypeInfoContent.length(), const_cast<char *>(extraTypeInfoContent.data()),
1929 false /* adopt */);
1930 auto infoList = reinterpret_cast<TList *>(buffer.ReadObject(TList::Class()));
1931 infoList->SetOwner(); // delete the TStreamerInfo items of the list
1932
1933 TObjLink *lnk = infoList->FirstLink();
1934 while (lnk) {
1935 auto info = reinterpret_cast<TStreamerInfo *>(lnk->GetObject());
1936 info->BuildCheck();
1937 infoMap[info->GetNumber()] = info->GetClass()->GetStreamerInfo();
1938 assert(info->GetNumber() == infoMap[info->GetNumber()]->GetNumber());
1939 lnk = lnk->Next();
1940 }
1941
1942 delete infoList;
1943
1944 return infoMap;
1945}
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
Definition RError.hxx:294
#define R__FORWARD_RESULT(res)
Short-hand to return an RResult<T> value from a subroutine to the calling stack frame.
Definition RError.hxx:292
#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:290
#define R__LOG_WARNING(...)
Definition RLogger.hxx:363
#define R__LOG_DEBUG(DEBUGLEVEL,...)
Definition RLogger.hxx:365
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define ROOT_RELEASE
Definition RVersion.hxx:29
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#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 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.
A helper class for piece-wise construction of an RClusterDescriptor.
RClusterDescriptorBuilder & ClusterId(DescriptorId_t clusterId)
RClusterDescriptorBuilder & NEntries(std::uint64_t nEntries)
RClusterDescriptorBuilder & FirstEntryIndex(std::uint64_t firstEntryIndex)
A helper class for piece-wise construction of an RClusterGroupDescriptor.
RClusterGroupDescriptorBuilder & PageListLocator(const RNTupleLocator &pageListLocator)
RClusterGroupDescriptorBuilder & MinEntry(std::uint64_t minEntry)
RClusterGroupDescriptorBuilder & ClusterGroupId(DescriptorId_t clusterGroupId)
RClusterGroupDescriptorBuilder & EntrySpan(std::uint64_t entrySpan)
RClusterGroupDescriptorBuilder & NClusters(std::uint32_t nClusters)
RClusterGroupDescriptorBuilder & PageListLength(std::uint64_t pageListLength)
A helper class for piece-wise construction of an RColumnDescriptor.
RColumnDescriptorBuilder & PhysicalColumnId(DescriptorId_t physicalColumnId)
RColumnDescriptorBuilder & Type(EColumnType type)
RColumnDescriptorBuilder & BitsOnStorage(std::uint16_t bitsOnStorage)
RColumnDescriptorBuilder & RepresentationIndex(std::uint16_t representationIndex)
RColumnDescriptorBuilder & FieldId(DescriptorId_t fieldId)
RColumnDescriptorBuilder & Index(std::uint32_t index)
RColumnDescriptorBuilder & FirstElementIndex(std::uint64_t firstElementIdx)
RResult< RColumnDescriptor > MakeDescriptor() const
Attempt to make a column descriptor.
RColumnDescriptorBuilder & LogicalColumnId(DescriptorId_t logicalColumnId)
RColumnDescriptorBuilder & ValueRange(double min, double max)
A helper class for piece-wise construction of an RExtraTypeInfoDescriptor.
RExtraTypeInfoDescriptorBuilder & Content(const std::string &content)
RExtraTypeInfoDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
RExtraTypeInfoDescriptorBuilder & TypeName(const std::string &typeName)
RExtraTypeInfoDescriptorBuilder & ContentId(EExtraTypeInfoIds contentId)
A helper class for piece-wise construction of an RFieldDescriptor.
RFieldDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
RFieldDescriptorBuilder & NRepetitions(std::uint64_t nRepetitions)
RFieldDescriptorBuilder & ProjectionSourceId(DescriptorId_t id)
RFieldDescriptorBuilder & FieldVersion(std::uint32_t fieldVersion)
RFieldDescriptorBuilder & Structure(const ENTupleStructure &structure)
RFieldDescriptorBuilder & TypeName(const std::string &typeName)
RResult< RFieldDescriptor > MakeDescriptor() const
Attempt to make a field descriptor.
RFieldDescriptorBuilder & FieldName(const std::string &fieldName)
RFieldDescriptorBuilder & ParentId(DescriptorId_t id)
RFieldDescriptorBuilder & TypeChecksum(const std::optional< std::uint32_t > typeChecksum)
RFieldDescriptorBuilder & TypeAlias(const std::string &typeAlias)
RFieldDescriptorBuilder & FieldId(DescriptorId_t fieldId)
RFieldDescriptorBuilder & FieldDescription(const std::string &fieldDescription)
A helper class for piece-wise construction of an RNTupleDescriptor.
RResult< void > AddFieldProjection(DescriptorId_t sourceId, DescriptorId_t targetId)
void BeginHeaderExtension()
Mark the beginning of the header extension; any fields and columns added after a call to this functio...
void ShiftAliasColumns(std::uint32_t offset)
If the descriptor is constructed in pieces consisting of physical and alias columns (regular and proj...
RResult< void > AddFieldLink(DescriptorId_t fieldId, DescriptorId_t linkId)
void AddToOnDiskFooterSize(std::uint64_t size)
The real footer size also include the page list envelopes.
void SetNTuple(const std::string_view name, const std::string_view description)
RResult< void > AddClusterGroup(RClusterGroupDescriptor &&clusterGroup)
RResult< void > AddColumn(RColumnDescriptor &&columnDesc)
RResult< void > AddExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc)
The serialization context is used for the piecewise serialization of a descriptor.
DescriptorId_t GetOnDiskColumnId(DescriptorId_t memId) const
const std::vector< DescriptorId_t > & GetOnDiskFieldList() const
Return a vector containing the in-memory field ID for each on-disk counterpart, in order,...
DescriptorId_t GetOnDiskFieldId(DescriptorId_t memId) const
DescriptorId_t GetMemColumnId(DescriptorId_t onDiskId) const
std::size_t GetHeaderExtensionOffset() const
Return the offset of the first element in fOnDisk2MemFieldIDs that is part of the schema extension.
DescriptorId_t GetMemClusterGroupId(DescriptorId_t onDiskId) const
DescriptorId_t GetMemClusterId(DescriptorId_t onDiskId) const
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 > DeserializeClusterSummary(const void *buffer, std::uint64_t bufSize, RClusterSummary &clusterSummary)
static std::uint32_t SerializeListFramePreamble(std::uint32_t nitems, void *buffer)
static RResult< std::uint32_t > DeserializeClusterGroup(const void *buffer, std::uint64_t bufSize, RClusterGroup &clusterGroup)
static std::uint32_t SerializeEnvelopePostscript(unsigned char *envelope, std::uint64_t size)
static std::uint32_t SerializeColumnType(ROOT::Experimental::EColumnType type, void *buffer)
static RContext SerializeHeader(void *buffer, const RNTupleDescriptor &desc)
static RResult< std::uint32_t > DeserializeColumnType(const void *buffer, ROOT::Experimental::EColumnType &type)
static std::uint32_t SerializeFeatureFlags(const std::vector< std::uint64_t > &flags, void *buffer)
static RResult< std::uint32_t > DeserializeExtraTypeInfoId(const void *buffer, ROOT::Experimental::EExtraTypeInfoIds &id)
static std::uint32_t DeserializeUInt16(const void *buffer, std::uint16_t &val)
static RResult< void > DeserializeHeader(const void *buffer, std::uint64_t bufSize, RNTupleDescriptorBuilder &descBuilder)
static RResult< void > DeserializeFooter(const void *buffer, std::uint64_t bufSize, RNTupleDescriptorBuilder &descBuilder)
static std::uint32_t SerializeString(const std::string &val, void *buffer)
static std::string SerializeStreamerInfos(const StreamerInfoMap_t &infos)
static RResult< std::uint32_t > DeserializeFrameHeader(const void *buffer, std::uint64_t bufSize, std::uint64_t &frameSize, std::uint32_t &nitems)
static std::uint32_t SerializePageList(void *buffer, const RNTupleDescriptor &desc, std::span< DescriptorId_t > physClusterIDs, const RContext &context)
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::uint32_t > DeserializeFieldStructure(const void *buffer, ROOT::Experimental::ENTupleStructure &structure)
static std::uint32_t SerializeClusterSummary(const RClusterSummary &clusterSummary, void *buffer)
static RResult< StreamerInfoMap_t > DeserializeStreamerInfos(const std::string &extraTypeInfoContent)
static std::uint32_t SerializeFramePostscript(void *frame, std::uint64_t size)
static std::uint32_t SerializeInt16(std::int16_t val, void *buffer)
static RResult< void > DeserializePageList(const void *buffer, std::uint64_t bufSize, DescriptorId_t clusterGroupId, RNTupleDescriptor &desc)
static std::uint32_t SerializeFieldStructure(ROOT::Experimental::ENTupleStructure structure, void *buffer)
While we could just interpret the enums as ints, we make the translation explicit in order to avoid a...
static std::uint32_t 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 > DeserializeSchemaDescription(const void *buffer, std::uint64_t bufSize, RNTupleDescriptorBuilder &descBuilder)
std::map< Int_t, TVirtualStreamerInfo * > StreamerInfoMap_t
static std::uint32_t SerializeLocator(const RNTupleLocator &locator, void *buffer)
static std::uint32_t SerializeInt32(std::int32_t val, void *buffer)
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 DeserializeUInt64(const void *buffer, std::uint64_t &val)
static RResult< std::uint32_t > DeserializeFeatureFlags(const void *buffer, std::uint64_t bufSize, std::vector< std::uint64_t > &flags)
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 std::uint32_t SerializeEnvelopeLink(const REnvelopeLink &envelopeLink, void *buffer)
static RResult< std::uint32_t > DeserializeString(const void *buffer, std::uint64_t bufSize, std::string &val)
static std::uint32_t SerializeRecordFramePreamble(void *buffer)
static std::uint32_t SerializeUInt16(std::uint16_t val, void *buffer)
static std::uint32_t SerializeClusterGroup(const RClusterGroup &clusterGroup, void *buffer)
static RResult< std::uint32_t > DeserializeEnvelopeLink(const void *buffer, std::uint64_t bufSize, REnvelopeLink &envelopeLink)
static std::uint32_t SerializeFooter(void *buffer, const RNTupleDescriptor &desc, const RContext &context)
static std::uint32_t SerializeInt64(std::int64_t val, void *buffer)
static RResult< std::uint32_t > DeserializeEnvelope(const void *buffer, std::uint64_t bufSize, std::uint16_t expectedType)
static std::uint32_t SerializeUInt32(std::uint32_t val, void *buffer)
static RResult< std::uint32_t > DeserializeLocator(const void *buffer, std::uint64_t bufSize, RNTupleLocator &locator)
static std::uint32_t SerializeExtraTypeInfoId(ROOT::Experimental::EExtraTypeInfoIds id, void *buffer)
Records the partition of data into pages for a particular column in a particular cluster.
Meta-data stored for every column of an ntuple.
std::optional< RValueRange > GetValueRange() const
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
Field specific extra type information from the header / extenstion header.
Meta-data stored for every field of an ntuple.
const std::string & GetFieldName() const
const std::string & GetTypeName() const
const std::string & GetFieldDescription() const
const std::vector< DescriptorId_t > & GetLogicalColumnIds() const
const std::string & GetTypeAlias() const
std::optional< std::uint32_t > GetTypeChecksum() const
const std::vector< DescriptorId_t > & GetExtendedColumnRepresentations() const
The on-storage meta-data of an ntuple.
RColumnDescriptorIterable GetColumnIterable() const
const RClusterDescriptor & GetClusterDescriptor(DescriptorId_t clusterId) const
DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level NTuple data fields.
RResult< void > AddClusterGroupDetails(DescriptorId_t clusterGroupId, std::vector< RClusterDescriptor > &clusterDescs)
Methods to load and drop cluster group details (cluster IDs and page locations)
const RColumnDescriptor & GetColumnDescriptor(DescriptorId_t columnId) const
RExtraTypeInfoDescriptorIterable GetExtraTypeInfoIterable() const
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
const RClusterGroupDescriptor & GetClusterGroupDescriptor(DescriptorId_t clusterGroupId) const
const std::string & GetDescription() const
const RHeaderExtension * GetHeaderExtension() const
Return header extension information; if the descriptor does not have a header extension,...
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
std::vector< std::uint64_t > GetFeatureFlags() 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:194
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
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
A doubly linked list.
Definition TList.h:38
static TClass * Class()
void Add(TObject *obj) override
Definition TList.h:83
Describes a persistent version of a class.
void BuildCheck(TFile *file=nullptr, Bool_t load=kTRUE) override
Check if built and consistent with the class dictionary.
constexpr RNTupleLocator::ELocatorType kTestLocatorType
constexpr ENTupleStructure kTestFutureFieldStructure
RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
EExtraTypeInfoIds
Used in RExtraTypeInfoDescriptor.
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
constexpr DescriptorId_t kInvalidDescriptorId
RNTupleLocator payload that is common for object stores using 64bit location information.
Generic information about the physical location of data.
std::uint8_t fReserved
Reserved for use by concrete storage backends.
ELocatorType fType
For non-disk locators, the value for the Type field.
std::variant< std::uint64_t, RNTupleLocatorObject64 > fPosition
Simple on-disk locators consisting of a 64-bit offset use variant type uint64_t; extended locators ha...