1#include "duckdb/common/field_writer.hpp"
2
3namespace duckdb {
4
5//===--------------------------------------------------------------------===//
6// Field Writer
7//===--------------------------------------------------------------------===//
8FieldWriter::FieldWriter(Serializer &serializer_p)
9 : serializer(serializer_p), buffer(make_uniq<BufferedSerializer>()), field_count(0), finalized(false) {
10 buffer->SetVersion(serializer.GetVersion());
11 buffer->is_query_plan = serializer.is_query_plan;
12}
13
14FieldWriter::~FieldWriter() {
15 if (Exception::UncaughtException()) {
16 return;
17 }
18 D_ASSERT(finalized);
19 // finalize should always have been called, unless this is destroyed as part of stack unwinding
20 D_ASSERT(!buffer);
21}
22
23void FieldWriter::WriteData(const_data_ptr_t buffer_ptr, idx_t write_size) {
24 D_ASSERT(buffer);
25 buffer->WriteData(buffer: buffer_ptr, write_size);
26}
27
28template <>
29void FieldWriter::Write(const string &val) {
30 Write<uint32_t>(element: (uint32_t)val.size());
31 if (!val.empty()) {
32 WriteData(buffer_ptr: const_data_ptr_cast(src: val.c_str()), write_size: val.size());
33 }
34}
35
36void FieldWriter::Finalize() {
37 D_ASSERT(buffer);
38 D_ASSERT(!finalized);
39 finalized = true;
40 serializer.Write<uint32_t>(element: field_count);
41 serializer.Write<uint64_t>(element: buffer->blob.size);
42 serializer.WriteData(buffer: buffer->blob.data.get(), write_size: buffer->blob.size);
43
44 buffer.reset();
45}
46
47//===--------------------------------------------------------------------===//
48// Field Deserializer
49//===--------------------------------------------------------------------===//
50FieldDeserializer::FieldDeserializer(Deserializer &root) : root(root), remaining_data(idx_t(-1)) {
51 SetVersion(root.GetVersion());
52}
53
54void FieldDeserializer::ReadData(data_ptr_t buffer, idx_t read_size) {
55 D_ASSERT(remaining_data != idx_t(-1));
56 D_ASSERT(read_size <= remaining_data);
57 root.ReadData(buffer, read_size);
58 remaining_data -= read_size;
59}
60
61idx_t FieldDeserializer::RemainingData() {
62 return remaining_data;
63}
64
65void FieldDeserializer::SetRemainingData(idx_t remaining_data) {
66 this->remaining_data = remaining_data;
67}
68
69//===--------------------------------------------------------------------===//
70// Field Reader
71//===--------------------------------------------------------------------===//
72FieldReader::FieldReader(Deserializer &source_p) : source(source_p), field_count(0), finalized(false) {
73 max_field_count = source_p.Read<uint32_t>();
74 total_size = source_p.Read<uint64_t>();
75 D_ASSERT(max_field_count > 0);
76 source.SetRemainingData(total_size);
77}
78
79FieldReader::~FieldReader() {
80 if (Exception::UncaughtException()) {
81 return;
82 }
83 D_ASSERT(finalized);
84}
85
86void FieldReader::Finalize() {
87 D_ASSERT(!finalized);
88 finalized = true;
89 if (field_count < max_field_count) {
90 // we can handle this case by calling source.ReadData(buffer, source.RemainingData())
91 throw SerializationException("Not all fields were read. This file might have been written with a newer version "
92 "of DuckDB and is incompatible with this version of DuckDB.");
93 }
94 D_ASSERT(source.RemainingData() == 0);
95}
96
97} // namespace duckdb
98