1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/common/serializer/format_serializer.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/field_writer.hpp"
12#include "duckdb/common/serializer.hpp"
13#include "duckdb/common/enum_util.hpp"
14#include "duckdb/common/serializer/serialization_traits.hpp"
15#include "duckdb/common/types/interval.hpp"
16#include "duckdb/common/types/string_type.hpp"
17#include "duckdb/common/unordered_map.hpp"
18#include "duckdb/common/unordered_set.hpp"
19
20namespace duckdb {
21
22class FormatSerializer {
23 friend Vector;
24
25protected:
26 bool serialize_enum_as_string = false;
27
28public:
29 // Serialize a value
30 template <class T>
31 typename std::enable_if<!std::is_enum<T>::value, void>::type WriteProperty(const char *tag, T &value) {
32 SetTag(tag);
33 WriteValue(value);
34 }
35
36 // Serialize an enum
37 template <class T>
38 typename std::enable_if<std::is_enum<T>::value, void>::type WriteProperty(const char *tag, T value) {
39 SetTag(tag);
40 if (serialize_enum_as_string) {
41 // Use the enum serializer to lookup tostring function
42 auto str = EnumUtil::ToChars(value);
43 WriteValue(str);
44 } else {
45 // Use the underlying type
46 WriteValue(static_cast<typename std::underlying_type<T>::type>(value));
47 }
48 }
49
50 // Optional pointer
51 template <class T>
52 void WriteOptionalProperty(const char *tag, T *ptr) {
53 SetTag(tag);
54 if (ptr == nullptr) {
55 OnOptionalBegin(present: false);
56 OnOptionalEnd(present: false);
57 } else {
58 OnOptionalBegin(present: true);
59 WriteValue(*ptr);
60 OnOptionalEnd(present: true);
61 }
62 }
63
64 // Optional unique_ptr
65 template <class T>
66 void WriteOptionalProperty(const char *tag, const unique_ptr<T> &ptr) {
67 SetTag(tag);
68 if (ptr == nullptr) {
69 OnOptionalBegin(present: false);
70 OnOptionalEnd(present: false);
71 } else {
72 OnOptionalBegin(present: true);
73 WriteValue(*ptr);
74 OnOptionalEnd(present: true);
75 }
76 }
77
78 // Special case: data_ptr_T
79 void WriteProperty(const char *tag, const_data_ptr_t ptr, idx_t count) {
80 SetTag(tag);
81 WriteDataPtr(ptr, count);
82 }
83
84protected:
85 // Unique Pointer Ref
86 template <typename T>
87 void WriteValue(const unique_ptr<T> &ptr) {
88 WriteValue(ptr.get());
89 }
90
91 // Pointer
92 template <typename T>
93 typename std::enable_if<std::is_pointer<T>::value, void>::type WriteValue(const T ptr) {
94 if (ptr == nullptr) {
95 WriteNull();
96 } else {
97 WriteValue(*ptr);
98 }
99 }
100
101 // Pair
102 template <class K, class V>
103 void WriteValue(const std::pair<K, V> &pair) {
104 OnPairBegin();
105 OnPairKeyBegin();
106 WriteValue(pair.first);
107 OnPairKeyEnd();
108 OnPairValueBegin();
109 WriteValue(pair.second);
110 OnPairValueEnd();
111 OnPairEnd();
112 }
113
114 // Vector
115 template <class T>
116 void WriteValue(const vector<T> &vec) {
117 auto count = vec.size();
118 OnListBegin(count);
119 for (auto &item : vec) {
120 WriteValue(item);
121 }
122 OnListEnd(count);
123 }
124
125 // UnorderedSet
126 // Serialized the same way as a list/vector
127 template <class T, class HASH, class CMP>
128 void WriteValue(const unordered_set<T, HASH, CMP> &set) {
129 auto count = set.size();
130 OnListBegin(count);
131 for (auto &item : set) {
132 WriteValue(item);
133 }
134 OnListEnd(count);
135 }
136
137 // Set
138 // Serialized the same way as a list/vector
139 template <class T, class HASH, class CMP>
140 void WriteValue(const set<T, HASH, CMP> &set) {
141 auto count = set.size();
142 OnListBegin(count);
143 for (auto &item : set) {
144 WriteValue(item);
145 }
146 OnListEnd(count);
147 }
148
149 // Map
150 template <class K, class V, class HASH, class CMP>
151 void WriteValue(const std::unordered_map<K, V, HASH, CMP> &map) {
152 auto count = map.size();
153 OnMapBegin(count);
154 for (auto &item : map) {
155 OnMapEntryBegin();
156 OnMapKeyBegin();
157 WriteValue(item.first);
158 OnMapKeyEnd();
159 OnMapValueBegin();
160 WriteValue(item.second);
161 OnMapValueEnd();
162 OnMapEntryEnd();
163 }
164 OnMapEnd(count);
165 }
166
167 // class or struct implementing `FormatSerialize(FormatSerializer& FormatSerializer)`;
168 template <typename T>
169 typename std::enable_if<has_serialize<T>::value>::type WriteValue(T &value) {
170 // Else, we defer to the .FormatSerialize method
171 OnObjectBegin();
172 value.FormatSerialize(*this);
173 OnObjectEnd();
174 }
175
176 // Handle setting a "tag" (optional)
177 virtual void SetTag(const char *tag) {
178 (void)tag;
179 }
180
181 // Hooks for subclasses to override to implement custom behavior
182 virtual void OnListBegin(idx_t count) {
183 (void)count;
184 }
185 virtual void OnListEnd(idx_t count) {
186 (void)count;
187 }
188 virtual void OnMapBegin(idx_t count) {
189 (void)count;
190 }
191 virtual void OnMapEnd(idx_t count) {
192 (void)count;
193 }
194 virtual void OnMapEntryBegin() {
195 }
196 virtual void OnMapEntryEnd() {
197 }
198 virtual void OnMapKeyBegin() {
199 }
200 virtual void OnMapKeyEnd() {
201 }
202 virtual void OnMapValueBegin() {
203 }
204 virtual void OnMapValueEnd() {
205 }
206 virtual void OnOptionalBegin(bool present) {
207 }
208 virtual void OnOptionalEnd(bool present) {
209 }
210 virtual void OnObjectBegin() {
211 }
212 virtual void OnObjectEnd() {
213 }
214 virtual void OnPairBegin() {
215 }
216 virtual void OnPairKeyBegin() {
217 }
218 virtual void OnPairKeyEnd() {
219 }
220 virtual void OnPairValueBegin() {
221 }
222 virtual void OnPairValueEnd() {
223 }
224 virtual void OnPairEnd() {
225 }
226
227 // Handle primitive types, a serializer needs to implement these.
228 virtual void WriteNull() = 0;
229 virtual void WriteValue(bool value) = 0;
230 virtual void WriteValue(uint8_t value) = 0;
231 virtual void WriteValue(int8_t value) = 0;
232 virtual void WriteValue(uint16_t value) = 0;
233 virtual void WriteValue(int16_t value) = 0;
234 virtual void WriteValue(uint32_t value) = 0;
235 virtual void WriteValue(int32_t value) = 0;
236 virtual void WriteValue(uint64_t value) = 0;
237 virtual void WriteValue(int64_t value) = 0;
238 virtual void WriteValue(hugeint_t value) = 0;
239 virtual void WriteValue(float value) = 0;
240 virtual void WriteValue(double value) = 0;
241 virtual void WriteValue(const string_t value) = 0;
242 virtual void WriteValue(const string &value) = 0;
243 virtual void WriteValue(const char *str) = 0;
244 virtual void WriteValue(interval_t value) = 0;
245 virtual void WriteDataPtr(const_data_ptr_t ptr, idx_t count) = 0;
246};
247
248} // namespace duckdb
249