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