blob: 1701236bf7e56b32d487c27b1b04b0b429d38efa [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001/*
2 * Copyright 2014 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef FLATBUFFERS_IDL_H_
18#define FLATBUFFERS_IDL_H_
19
James Kuszmaul3b15b0c2022-11-08 14:03:16 -080020#include <algorithm>
James Kuszmaul8e62b022022-03-22 09:33:25 -070021#include <functional>
Austin Schuhe89fa2d2019-08-14 20:24:23 -070022#include <map>
23#include <memory>
24#include <stack>
25
26#include "flatbuffers/base.h"
27#include "flatbuffers/flatbuffers.h"
28#include "flatbuffers/flexbuffers.h"
29#include "flatbuffers/hash.h"
30#include "flatbuffers/reflection.h"
31
Austin Schuhe89fa2d2019-08-14 20:24:23 -070032// This file defines the data types representing a parsed IDL (Interface
33// Definition Language) / schema file.
34
35// Limits maximum depth of nested objects.
James Kuszmaul8e62b022022-03-22 09:33:25 -070036// Prevents stack overflow while parse scheme, or json, or flexbuffer.
Austin Schuhe89fa2d2019-08-14 20:24:23 -070037#if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
38# define FLATBUFFERS_MAX_PARSING_DEPTH 64
39#endif
40
41namespace flatbuffers {
42
43// The order of these matters for Is*() functions below.
44// Additionally, Parser::ParseType assumes bool..string is a contiguous range
45// of type tokens.
46// clang-format off
47#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
Austin Schuh272c6132020-11-14 16:37:52 -080048 TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
49 TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) /* begin scalar/int */ \
50 TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool) \
51 TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8) \
52 TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
53 TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16) \
54 TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16) \
55 TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32) \
56 TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32) \
57 TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64) \
58 TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64) /* end int */ \
59 TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32) /* begin float */ \
60 TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double) /* end float/scalar */
Austin Schuhe89fa2d2019-08-14 20:24:23 -070061#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
Austin Schuh272c6132020-11-14 16:37:52 -080062 TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>) \
63 TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>) \
64 TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>) \
65 TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070066#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
Austin Schuh272c6132020-11-14 16:37:52 -080067 TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070068// The fields are:
69// - enum
70// - FlatBuffers schema type.
71// - C++ type.
72// - Java type.
73// - Go type.
74// - C# / .Net type.
75// - Python type.
Austin Schuhe89fa2d2019-08-14 20:24:23 -070076// - Kotlin type.
James Kuszmaul8e62b022022-03-22 09:33:25 -070077// - Rust type.
Austin Schuhe89fa2d2019-08-14 20:24:23 -070078
79// using these macros, we can now write code dealing with types just once, e.g.
80
81/*
82switch (type) {
83 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
84 RTYPE, KTYPE) \
85 case BASE_TYPE_ ## ENUM: \
86 // do something specific to CTYPE here
87 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
88 #undef FLATBUFFERS_TD
89}
90*/
91
Austin Schuh272c6132020-11-14 16:37:52 -080092// If not all FLATBUFFERS_GEN_() arguments are necessary for implementation
93// of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed).
94// In the above example, only CTYPE is used to generate the code, it can be rewritten:
95
96/*
97switch (type) {
98 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
99 case BASE_TYPE_ ## ENUM: \
100 // do something specific to CTYPE here
101 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
102 #undef FLATBUFFERS_TD
103}
104*/
105
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700106#define FLATBUFFERS_GEN_TYPES(TD) \
107 FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
108 FLATBUFFERS_GEN_TYPES_POINTER(TD) \
109 FLATBUFFERS_GEN_TYPE_ARRAY(TD)
110
111// Create an enum for all the types above.
112#ifdef __GNUC__
113__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
114#endif
115enum BaseType {
Austin Schuh272c6132020-11-14 16:37:52 -0800116 #define FLATBUFFERS_TD(ENUM, ...) \
117 BASE_TYPE_ ## ENUM,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700118 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
119 #undef FLATBUFFERS_TD
120};
121
Austin Schuh272c6132020-11-14 16:37:52 -0800122#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
123 static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
124 "define largest_scalar_t as " #CTYPE);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700125 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
126#undef FLATBUFFERS_TD
127
128inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
129 t <= BASE_TYPE_DOUBLE; }
130inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
131 t <= BASE_TYPE_ULONG; }
132inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
133 t == BASE_TYPE_DOUBLE; }
134inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
135 t == BASE_TYPE_ULONG; }
136inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
137inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
138 t <= BASE_TYPE_UCHAR; }
139
140inline bool IsUnsigned(BaseType t) {
141 return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
142 (t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) ||
143 (t == BASE_TYPE_ULONG);
144}
145
146// clang-format on
147
148extern const char *const kTypeNames[];
149extern const char kTypeSizes[];
150
151inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
152
153struct StructDef;
154struct EnumDef;
155class Parser;
156
157// Represents any type in the IDL, which is a combination of the BaseType
158// and additional information for vectors/structs_.
159struct Type {
160 explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
161 EnumDef *_ed = nullptr, uint16_t _fixed_length = 0)
162 : base_type(_base_type),
163 element(BASE_TYPE_NONE),
164 struct_def(_sd),
165 enum_def(_ed),
166 fixed_length(_fixed_length) {}
167
Austin Schuh2dd86a92022-09-14 21:19:23 -0700168 bool operator==(const Type &o) const {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700169 return base_type == o.base_type && element == o.element &&
170 struct_def == o.struct_def && enum_def == o.enum_def;
171 }
172
173 Type VectorType() const {
174 return Type(element, struct_def, enum_def, fixed_length);
175 }
176
177 Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
178
179 bool Deserialize(const Parser &parser, const reflection::Type *type);
180
181 BaseType base_type;
182 BaseType element; // only set if t == BASE_TYPE_VECTOR
183 StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
184 EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
185 // or for an integral type derived from an enum.
186 uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY
187};
188
189// Represents a parsed scalar value, it's type, and field offset.
190struct Value {
191 Value()
192 : constant("0"),
193 offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
194 Type type;
195 std::string constant;
196 voffset_t offset;
197};
198
199// Helper class that retains the original order of a set of identifiers and
200// also provides quick lookup.
201template<typename T> class SymbolTable {
202 public:
203 ~SymbolTable() {
204 for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
205 }
206
207 bool Add(const std::string &name, T *e) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700208 vec.emplace_back(e);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700209 auto it = dict.find(name);
210 if (it != dict.end()) return true;
211 dict[name] = e;
212 return false;
213 }
214
215 void Move(const std::string &oldname, const std::string &newname) {
216 auto it = dict.find(oldname);
217 if (it != dict.end()) {
218 auto obj = it->second;
219 dict.erase(it);
220 dict[newname] = obj;
221 } else {
222 FLATBUFFERS_ASSERT(false);
223 }
224 }
225
226 T *Lookup(const std::string &name) const {
227 auto it = dict.find(name);
228 return it == dict.end() ? nullptr : it->second;
229 }
230
231 public:
232 std::map<std::string, T *> dict; // quick lookup
233 std::vector<T *> vec; // Used to iterate in order of insertion
234};
235
236// A name space, as set in the schema.
237struct Namespace {
238 Namespace() : from_table(0) {}
239
Austin Schuh272c6132020-11-14 16:37:52 -0800240 // Given a (potentially unqualified) name, return the "fully qualified" name
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700241 // which has a full namespaced descriptor.
242 // With max_components you can request less than the number of components
243 // the current namespace has.
244 std::string GetFullyQualifiedName(const std::string &name,
245 size_t max_components = 1000) const;
246
247 std::vector<std::string> components;
248 size_t from_table; // Part of the namespace corresponds to a message/table.
249};
250
251inline bool operator<(const Namespace &a, const Namespace &b) {
252 size_t min_size = std::min(a.components.size(), b.components.size());
253 for (size_t i = 0; i < min_size; ++i) {
254 if (a.components[i] != b.components[i])
255 return a.components[i] < b.components[i];
256 }
257 return a.components.size() < b.components.size();
258}
259
260// Base class for all definition types (fields, structs_, enums_).
261struct Definition {
262 Definition()
263 : generated(false),
264 defined_namespace(nullptr),
265 serialized_location(0),
266 index(-1),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700267 refcount(1),
268 declaration_file(nullptr) {}
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700269
270 flatbuffers::Offset<
271 flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
272 SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
273
274 bool DeserializeAttributes(Parser &parser,
275 const Vector<Offset<reflection::KeyValue>> *attrs);
276
277 std::string name;
278 std::string file;
279 std::vector<std::string> doc_comment;
280 SymbolTable<Value> attributes;
281 bool generated; // did we already output code for this definition?
282 Namespace *defined_namespace; // Where it was defined.
283
284 // For use with Serialize()
285 uoffset_t serialized_location;
286 int index; // Inside the vector it is stored.
287 int refcount;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700288 const std::string *declaration_file;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700289};
290
291struct FieldDef : public Definition {
292 FieldDef()
293 : deprecated(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700294 key(false),
295 shared(false),
296 native_inline(false),
297 flexbuffer(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700298 presence(kDefault),
Austin Schuh2dd86a92022-09-14 21:19:23 -0700299 nested_flatbuffer(nullptr),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700300 padding(0) {}
301
302 Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
303 const Parser &parser) const;
304
305 bool Deserialize(Parser &parser, const reflection::Field *field);
306
Austin Schuh272c6132020-11-14 16:37:52 -0800307 bool IsScalarOptional() const {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700308 return IsScalar(value.type.base_type) && IsOptional();
Austin Schuh272c6132020-11-14 16:37:52 -0800309 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700310 bool IsOptional() const { return presence == kOptional; }
311 bool IsRequired() const { return presence == kRequired; }
312 bool IsDefault() const { return presence == kDefault; }
Austin Schuh272c6132020-11-14 16:37:52 -0800313
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700314 Value value;
315 bool deprecated; // Field is allowed to be present in old data, but can't be.
316 // written in new data nor accessed in new code.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700317 bool key; // Field functions as a key for creating sorted vectors.
318 bool shared; // Field will be using string pooling (i.e. CreateSharedString)
319 // as default serialization behavior if field is a string.
320 bool native_inline; // Field will be defined inline (instead of as a pointer)
321 // for native tables if field is a struct.
322 bool flexbuffer; // This field contains FlexBuffer data.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700323
324 enum Presence {
325 // Field must always be present.
326 kRequired,
327 // Non-presence should be signalled to and controlled by users.
328 kOptional,
329 // Non-presence is hidden from users.
330 // Implementations may omit writing default values.
331 kDefault,
332 };
333 Presence static MakeFieldPresence(bool optional, bool required) {
334 FLATBUFFERS_ASSERT(!(required && optional));
335 // clang-format off
336 return required ? FieldDef::kRequired
337 : optional ? FieldDef::kOptional
338 : FieldDef::kDefault;
339 // clang-format on
340 }
341 Presence presence;
342
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700343 StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
344 size_t padding; // Bytes to always pad after this field.
345};
346
347struct StructDef : public Definition {
348 StructDef()
349 : fixed(false),
350 predecl(true),
351 sortbysize(true),
352 has_key(false),
353 minalign(1),
354 bytesize(0) {}
355
356 void PadLastField(size_t min_align) {
357 auto padding = PaddingBytes(bytesize, min_align);
358 bytesize += padding;
359 if (fields.vec.size()) fields.vec.back()->padding = padding;
360 }
361
362 Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
363 const Parser &parser) const;
364
365 bool Deserialize(Parser &parser, const reflection::Object *object);
366
367 SymbolTable<FieldDef> fields;
368
369 bool fixed; // If it's struct, not a table.
370 bool predecl; // If it's used before it was defined.
371 bool sortbysize; // Whether fields come in the declaration or size order.
372 bool has_key; // It has a key field.
373 size_t minalign; // What the whole object needs to be aligned to.
374 size_t bytesize; // Size if fixed.
375
376 flatbuffers::unique_ptr<std::string> original_location;
377};
378
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700379struct EnumDef;
380struct EnumValBuilder;
381
382struct EnumVal {
Austin Schuh272c6132020-11-14 16:37:52 -0800383 Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
384 const Parser &parser) const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700385
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800386 bool Deserialize(Parser &parser, const reflection::EnumVal *val);
387
388 flatbuffers::Offset<
389 flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
390 SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
391
392 bool DeserializeAttributes(Parser &parser,
393 const Vector<Offset<reflection::KeyValue>> *attrs);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700394
395 uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
396 int64_t GetAsInt64() const { return value; }
397 bool IsZero() const { return 0 == value; }
398 bool IsNonZero() const { return !IsZero(); }
399
400 std::string name;
401 std::vector<std::string> doc_comment;
402 Type union_type;
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800403 SymbolTable<Value> attributes;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700404
405 private:
406 friend EnumDef;
407 friend EnumValBuilder;
408 friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
409
410 EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
411 EnumVal() : value(0) {}
412
413 int64_t value;
414};
415
416struct EnumDef : public Definition {
417 EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
418
419 Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
420 const Parser &parser) const;
421
422 bool Deserialize(Parser &parser, const reflection::Enum *values);
423
424 template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
425 void SortByValue();
426 void RemoveDuplicates();
427
428 std::string AllFlags() const;
429 const EnumVal *MinValue() const;
430 const EnumVal *MaxValue() const;
431 // Returns the number of integer steps from v1 to v2.
432 uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
433 // Returns the number of integer steps from Min to Max.
434 uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
435
436 EnumVal *ReverseLookup(int64_t enum_idx,
437 bool skip_union_default = false) const;
438 EnumVal *FindByValue(const std::string &constant) const;
439
440 std::string ToString(const EnumVal &ev) const {
441 return IsUInt64() ? NumToString(ev.GetAsUInt64())
442 : NumToString(ev.GetAsInt64());
443 }
444
445 size_t size() const { return vals.vec.size(); }
446
Austin Schuh272c6132020-11-14 16:37:52 -0800447 const std::vector<EnumVal *> &Vals() const { return vals.vec; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700448
449 const EnumVal *Lookup(const std::string &enum_name) const {
450 return vals.Lookup(enum_name);
451 }
452
453 bool is_union;
454 // Type is a union which uses type aliases where at least one type is
455 // available under two different names.
456 bool uses_multiple_type_instances;
457 Type underlying_type;
458
459 private:
460 bool IsUInt64() const {
461 return (BASE_TYPE_ULONG == underlying_type.base_type);
462 }
463
464 friend EnumValBuilder;
465 SymbolTable<EnumVal> vals;
466};
467
Austin Schuh272c6132020-11-14 16:37:52 -0800468inline bool IsString(const Type &type) {
469 return type.base_type == BASE_TYPE_STRING;
470}
471
472inline bool IsStruct(const Type &type) {
473 return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
474}
475
Austin Schuh2dd86a92022-09-14 21:19:23 -0700476inline bool IsTable(const Type &type) {
477 return type.base_type == BASE_TYPE_STRUCT && !type.struct_def->fixed;
478}
479
Austin Schuh272c6132020-11-14 16:37:52 -0800480inline bool IsUnion(const Type &type) {
481 return type.enum_def != nullptr && type.enum_def->is_union;
482}
483
James Kuszmaul8e62b022022-03-22 09:33:25 -0700484inline bool IsUnionType(const Type &type) {
485 return IsUnion(type) && IsInteger(type.base_type);
486}
487
Austin Schuh272c6132020-11-14 16:37:52 -0800488inline bool IsVector(const Type &type) {
489 return type.base_type == BASE_TYPE_VECTOR;
490}
491
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800492inline bool IsVectorOfStruct(const Type &type) {
Austin Schuh2dd86a92022-09-14 21:19:23 -0700493 return IsVector(type) && IsStruct(type.VectorType());
494}
495
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800496inline bool IsVectorOfTable(const Type &type) {
Austin Schuh2dd86a92022-09-14 21:19:23 -0700497 return IsVector(type) && IsTable(type.VectorType());
498}
499
Austin Schuh272c6132020-11-14 16:37:52 -0800500inline bool IsArray(const Type &type) {
501 return type.base_type == BASE_TYPE_ARRAY;
502}
503
504inline bool IsSeries(const Type &type) {
505 return IsVector(type) || IsArray(type);
506}
507
508inline bool IsEnum(const Type &type) {
509 return type.enum_def != nullptr && IsInteger(type.base_type);
510}
511
512inline size_t InlineSize(const Type &type) {
513 return IsStruct(type)
514 ? type.struct_def->bytesize
515 : (IsArray(type)
516 ? InlineSize(type.VectorType()) * type.fixed_length
517 : SizeOf(type.base_type));
518}
519
520inline size_t InlineAlignment(const Type &type) {
521 if (IsStruct(type)) {
522 return type.struct_def->minalign;
523 } else if (IsArray(type)) {
524 return IsStruct(type.VectorType()) ? type.struct_def->minalign
525 : SizeOf(type.element);
526 } else {
527 return SizeOf(type.base_type);
528 }
529}
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700530inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) {
531 return lhs.value == rhs.value;
532}
533inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
534 return !(lhs == rhs);
535}
536
537inline bool EqualByName(const Type &a, const Type &b) {
538 return a.base_type == b.base_type && a.element == b.element &&
539 (a.struct_def == b.struct_def ||
540 a.struct_def->name == b.struct_def->name) &&
541 (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
542}
543
544struct RPCCall : public Definition {
Austin Schuh272c6132020-11-14 16:37:52 -0800545 Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder,
546 const Parser &parser) const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700547
548 bool Deserialize(Parser &parser, const reflection::RPCCall *call);
549
550 StructDef *request, *response;
551};
552
553struct ServiceDef : public Definition {
Austin Schuh272c6132020-11-14 16:37:52 -0800554 Offset<reflection::Service> Serialize(FlatBufferBuilder *builder,
555 const Parser &parser) const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700556 bool Deserialize(Parser &parser, const reflection::Service *service);
557
558 SymbolTable<RPCCall> calls;
559};
560
Austin Schuh2dd86a92022-09-14 21:19:23 -0700561struct IncludedFile {
562 // The name of the schema file being included, as defined in the .fbs file.
563 // This includes the prefix (e.g., include "foo/bar/baz.fbs" would mean this
564 // value is "foo/bar/baz.fbs").
565 std::string schema_name;
566
567 // The filename of where the included file was found, after searching the
568 // relative paths plus any other paths included with `flatc -I ...`. Note,
569 // while this is sometimes the same as schema_name, it is not always, since it
570 // can be defined relative to where flatc was invoked.
571 std::string filename;
572};
573
574// Since IncludedFile is contained within a std::set, need to provide ordering.
575inline bool operator<(const IncludedFile &a, const IncludedFile &b) {
576 return a.filename < b.filename;
577}
578
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700579// Container of options that may apply to any of the source/text generators.
580struct IDLOptions {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700581 // field case style options for C++
582 enum CaseStyle { CaseStyle_Unchanged = 0, CaseStyle_Upper, CaseStyle_Lower };
583
Austin Schuh272c6132020-11-14 16:37:52 -0800584 bool gen_jvmstatic;
585 // Use flexbuffers instead for binary and text generation
586 bool use_flexbuffers;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700587 bool strict_json;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700588 bool output_default_scalars_in_json;
589 int indent_step;
590 bool output_enum_identifiers;
591 bool prefixed_enums;
592 bool scoped_enums;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700593 bool swift_implementation_only;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700594 bool include_dependence_headers;
595 bool mutable_buffer;
596 bool one_file;
597 bool proto_mode;
598 bool proto_oneof_union;
599 bool generate_all;
600 bool skip_unexpected_fields_in_json;
601 bool generate_name_strings;
602 bool generate_object_based_api;
603 bool gen_compare;
604 std::string cpp_object_api_pointer_type;
605 std::string cpp_object_api_string_type;
606 bool cpp_object_api_string_flexible_constructor;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700607 CaseStyle cpp_object_api_field_case_style;
Austin Schuh272c6132020-11-14 16:37:52 -0800608 bool cpp_direct_copy;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700609 bool gen_nullable;
Austin Schuh272c6132020-11-14 16:37:52 -0800610 bool java_checkerframework;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700611 bool gen_generated;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700612 bool gen_json_coders;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700613 std::string object_prefix;
614 std::string object_suffix;
615 bool union_value_namespacing;
616 bool allow_non_utf8;
617 bool natural_utf8;
618 std::string include_prefix;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700619 bool keep_prefix;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700620 bool binary_schema_comments;
621 bool binary_schema_builtins;
Austin Schuh272c6132020-11-14 16:37:52 -0800622 bool binary_schema_gen_embed;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700623 std::string go_import;
624 std::string go_namespace;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700625 bool protobuf_ascii_alike;
626 bool size_prefixed;
627 std::string root_type;
628 bool force_defaults;
Austin Schuh272c6132020-11-14 16:37:52 -0800629 bool java_primitive_has_method;
630 bool cs_gen_json_serializer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700631 std::vector<std::string> cpp_includes;
Austin Schuh272c6132020-11-14 16:37:52 -0800632 std::string cpp_std;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700633 bool cpp_static_reflection;
Austin Schuh272c6132020-11-14 16:37:52 -0800634 std::string proto_namespace_suffix;
635 std::string filename_suffix;
636 std::string filename_extension;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700637 bool no_warnings;
638 bool warnings_as_errors;
639 std::string project_root;
640 bool cs_global_alias;
641 bool json_nested_flatbuffers;
642 bool json_nested_flexbuffers;
643 bool json_nested_legacy_flatbuffers;
644 bool ts_flat_file;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700645 bool no_leak_private_annotations;
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800646 bool require_json_eof;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700647
648 // Possible options for the more general generator below.
649 enum Language {
650 kJava = 1 << 0,
651 kCSharp = 1 << 1,
652 kGo = 1 << 2,
653 kCpp = 1 << 3,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700654 kPython = 1 << 5,
655 kPhp = 1 << 6,
656 kJson = 1 << 7,
657 kBinary = 1 << 8,
658 kTs = 1 << 9,
659 kJsonSchema = 1 << 10,
660 kDart = 1 << 11,
661 kLua = 1 << 12,
662 kLobster = 1 << 13,
663 kRust = 1 << 14,
664 kKotlin = 1 << 15,
Austin Schuh272c6132020-11-14 16:37:52 -0800665 kSwift = 1 << 16,
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800666 kNim = 1 << 17,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700667 kMAX
668 };
669
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700670 enum MiniReflect { kNone, kTypes, kTypesAndNames };
671
672 MiniReflect mini_reflect;
673
Austin Schuh58b9b472020-11-25 19:12:44 -0800674 // If set, require all fields in a table to be explicitly numbered.
675 bool require_explicit_ids;
676
James Kuszmaul8e62b022022-03-22 09:33:25 -0700677 // If set, implement serde::Serialize for generated Rust types
678 bool rust_serialize;
679
680 // If set, generate rust types in individual files with a root module file.
681 bool rust_module_root_file;
682
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700683 // The corresponding language bit will be set if a language is included
684 // for code generation.
685 unsigned long lang_to_generate;
686
Austin Schuh272c6132020-11-14 16:37:52 -0800687 // If set (default behavior), empty string fields will be set to nullptr to
688 // make the flatbuffer more compact.
689 bool set_empty_strings_to_null;
690
691 // If set (default behavior), empty vector fields will be set to nullptr to
692 // make the flatbuffer more compact.
693 bool set_empty_vectors_to_null;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700694
695 IDLOptions()
Austin Schuh272c6132020-11-14 16:37:52 -0800696 : gen_jvmstatic(false),
697 use_flexbuffers(false),
698 strict_json(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700699 output_default_scalars_in_json(false),
700 indent_step(2),
701 output_enum_identifiers(true),
702 prefixed_enums(true),
703 scoped_enums(false),
Austin Schuh2dd86a92022-09-14 21:19:23 -0700704 swift_implementation_only(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700705 include_dependence_headers(true),
706 mutable_buffer(false),
707 one_file(false),
708 proto_mode(false),
709 proto_oneof_union(false),
710 generate_all(false),
711 skip_unexpected_fields_in_json(false),
712 generate_name_strings(false),
713 generate_object_based_api(false),
714 gen_compare(false),
715 cpp_object_api_pointer_type("std::unique_ptr"),
716 cpp_object_api_string_flexible_constructor(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700717 cpp_object_api_field_case_style(CaseStyle_Unchanged),
Austin Schuh272c6132020-11-14 16:37:52 -0800718 cpp_direct_copy(true),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700719 gen_nullable(false),
Austin Schuh272c6132020-11-14 16:37:52 -0800720 java_checkerframework(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700721 gen_generated(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700722 gen_json_coders(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700723 object_suffix("T"),
724 union_value_namespacing(true),
725 allow_non_utf8(false),
726 natural_utf8(false),
Austin Schuh2dd86a92022-09-14 21:19:23 -0700727 keep_prefix(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700728 binary_schema_comments(false),
729 binary_schema_builtins(false),
Austin Schuh272c6132020-11-14 16:37:52 -0800730 binary_schema_gen_embed(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700731 protobuf_ascii_alike(false),
732 size_prefixed(false),
733 force_defaults(false),
Austin Schuh272c6132020-11-14 16:37:52 -0800734 java_primitive_has_method(false),
735 cs_gen_json_serializer(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700736 cpp_static_reflection(false),
Austin Schuh272c6132020-11-14 16:37:52 -0800737 filename_suffix("_generated"),
738 filename_extension(),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700739 no_warnings(false),
740 warnings_as_errors(false),
741 project_root(""),
742 cs_global_alias(false),
743 json_nested_flatbuffers(true),
744 json_nested_flexbuffers(true),
745 json_nested_legacy_flatbuffers(false),
746 ts_flat_file(false),
Austin Schuh2dd86a92022-09-14 21:19:23 -0700747 no_leak_private_annotations(false),
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800748 require_json_eof(true),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700749 mini_reflect(IDLOptions::kNone),
Austin Schuh58b9b472020-11-25 19:12:44 -0800750 require_explicit_ids(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700751 rust_serialize(false),
752 rust_module_root_file(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700753 lang_to_generate(0),
Austin Schuh272c6132020-11-14 16:37:52 -0800754 set_empty_strings_to_null(true),
755 set_empty_vectors_to_null(true) {}
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700756};
757
758// This encapsulates where the parser is in the current source file.
759struct ParserState {
760 ParserState()
761 : cursor_(nullptr),
762 line_start_(nullptr),
763 line_(0),
764 token_(-1),
765 attr_is_trivial_ascii_string_(true) {}
766
767 protected:
768 void ResetState(const char *source) {
769 cursor_ = source;
770 line_ = 0;
771 MarkNewLine();
772 }
773
774 void MarkNewLine() {
775 line_start_ = cursor_;
776 line_ += 1;
777 }
778
779 int64_t CursorPosition() const {
780 FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
781 return static_cast<int64_t>(cursor_ - line_start_);
782 }
783
784 const char *cursor_;
785 const char *line_start_;
786 int line_; // the current line being parsed
787 int token_;
788
789 // Flag: text in attribute_ is true ASCII string without escape
790 // sequences. Only printable ASCII (without [\t\r\n]).
791 // Used for number-in-string (and base64 string in future).
792 bool attr_is_trivial_ascii_string_;
793 std::string attribute_;
794 std::vector<std::string> doc_comment_;
795};
796
797// A way to make error propagation less error prone by requiring values to be
798// checked.
799// Once you create a value of this type you must either:
800// - Call Check() on it.
801// - Copy or assign it to another value.
802// Failure to do so leads to an assert.
803// This guarantees that this as return value cannot be ignored.
804class CheckedError {
805 public:
806 explicit CheckedError(bool error)
807 : is_error_(error), has_been_checked_(false) {}
808
809 CheckedError &operator=(const CheckedError &other) {
810 is_error_ = other.is_error_;
811 has_been_checked_ = false;
812 other.has_been_checked_ = true;
813 return *this;
814 }
815
816 CheckedError(const CheckedError &other) {
817 *this = other; // Use assignment operator.
818 }
819
820 ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
821
822 bool Check() {
823 has_been_checked_ = true;
824 return is_error_;
825 }
826
827 private:
828 bool is_error_;
829 mutable bool has_been_checked_;
830};
831
832// Additionally, in GCC we can get these errors statically, for additional
833// assurance:
834// clang-format off
835#ifdef __GNUC__
836#define FLATBUFFERS_CHECKED_ERROR CheckedError \
837 __attribute__((warn_unused_result))
838#else
839#define FLATBUFFERS_CHECKED_ERROR CheckedError
840#endif
841// clang-format on
842
843class Parser : public ParserState {
844 public:
845 explicit Parser(const IDLOptions &options = IDLOptions())
846 : current_namespace_(nullptr),
847 empty_namespace_(nullptr),
Austin Schuh272c6132020-11-14 16:37:52 -0800848 flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700849 root_struct_def_(nullptr),
850 opts(options),
851 uses_flexbuffers_(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700852 has_warning_(false),
853 advanced_features_(0),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700854 source_(nullptr),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700855 anonymous_counter_(0),
856 parse_depth_counter_(0) {
Austin Schuh272c6132020-11-14 16:37:52 -0800857 if (opts.force_defaults) { builder_.ForceDefaults(true); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700858 // Start out with the empty namespace being current.
859 empty_namespace_ = new Namespace();
860 namespaces_.push_back(empty_namespace_);
861 current_namespace_ = empty_namespace_;
862 known_attributes_["deprecated"] = true;
863 known_attributes_["required"] = true;
864 known_attributes_["key"] = true;
865 known_attributes_["shared"] = true;
866 known_attributes_["hash"] = true;
867 known_attributes_["id"] = true;
868 known_attributes_["force_align"] = true;
869 known_attributes_["bit_flags"] = true;
870 known_attributes_["original_order"] = true;
871 known_attributes_["nested_flatbuffer"] = true;
872 known_attributes_["csharp_partial"] = true;
873 known_attributes_["streaming"] = true;
874 known_attributes_["idempotent"] = true;
875 known_attributes_["cpp_type"] = true;
876 known_attributes_["cpp_ptr_type"] = true;
877 known_attributes_["cpp_ptr_type_get"] = true;
878 known_attributes_["cpp_str_type"] = true;
879 known_attributes_["cpp_str_flex_ctor"] = true;
880 known_attributes_["native_inline"] = true;
881 known_attributes_["native_custom_alloc"] = true;
882 known_attributes_["native_type"] = true;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700883 known_attributes_["native_type_pack_name"] = true;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700884 known_attributes_["native_default"] = true;
885 known_attributes_["flexbuffer"] = true;
886 known_attributes_["private"] = true;
887 }
888
889 ~Parser() {
890 for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
891 delete *it;
892 }
893 }
894
895 // Parse the string containing either schema or JSON data, which will
896 // populate the SymbolTable's or the FlatBufferBuilder above.
897 // include_paths is used to resolve any include statements, and typically
898 // should at least include the project path (where you loaded source_ from).
899 // include_paths must be nullptr terminated if specified.
900 // If include_paths is nullptr, it will attempt to load from the current
901 // directory.
902 // If the source was loaded from a file and isn't an include file,
903 // supply its name in source_filename.
904 // All paths specified in this call must be in posix format, if you accept
905 // paths from user input, please call PosixPath on them first.
906 bool Parse(const char *_source, const char **include_paths = nullptr,
907 const char *source_filename = nullptr);
908
Austin Schuh58b9b472020-11-25 19:12:44 -0800909 bool ParseJson(const char *json, const char *json_filename = nullptr);
910
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800911 // Returns the number of characters were consumed when parsing a JSON string.
912 std::ptrdiff_t BytesConsumed() const;
913
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700914 // Set the root type. May override the one set in the schema.
915 bool SetRootType(const char *name);
916
917 // Mark all definitions as already having code generated.
918 void MarkGenerated();
919
920 // Get the files recursively included by the given file. The returned
921 // container will have at least the given file.
922 std::set<std::string> GetIncludedFilesRecursive(
923 const std::string &file_name) const;
924
925 // Fills builder_ with a binary version of the schema parsed.
926 // See reflection/reflection.fbs
927 void Serialize();
928
929 // Deserialize a schema buffer
930 bool Deserialize(const uint8_t *buf, const size_t size);
931
932 // Fills internal structure as if the schema passed had been loaded by parsing
933 // with Parse except that included filenames will not be populated.
Austin Schuh272c6132020-11-14 16:37:52 -0800934 bool Deserialize(const reflection::Schema *schema);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700935
Austin Schuh272c6132020-11-14 16:37:52 -0800936 Type *DeserializeType(const reflection::Type *type);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700937
938 // Checks that the schema represented by this parser is a safe evolution
939 // of the schema provided. Returns non-empty error on any problems.
940 std::string ConformTo(const Parser &base);
941
942 // Similar to Parse(), but now only accepts JSON to be parsed into a
943 // FlexBuffer.
944 bool ParseFlexBuffer(const char *source, const char *source_filename,
945 flexbuffers::Builder *builder);
946
947 StructDef *LookupStruct(const std::string &id) const;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700948 StructDef *LookupStructThruParentNamespaces(const std::string &id) const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700949
950 std::string UnqualifiedName(const std::string &fullQualifiedName);
951
952 FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
953
Austin Schuh272c6132020-11-14 16:37:52 -0800954 // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars
955 // in a schema.
956 // @param opts Options used to parce a schema and generate code.
957 static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts);
958
Austin Schuh2dd86a92022-09-14 21:19:23 -0700959 // Get the set of included files that are directly referenced by the file
960 // being parsed. This does not include files that are transitively included by
961 // others includes.
962 std::vector<IncludedFile> GetIncludedFiles() const;
963
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700964 private:
James Kuszmaul8e62b022022-03-22 09:33:25 -0700965 class ParseDepthGuard;
966
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700967 void Message(const std::string &msg);
968 void Warning(const std::string &msg);
969 FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
970 FLATBUFFERS_CHECKED_ERROR Next();
971 FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
972 bool Is(int t) const;
973 bool IsIdent(const char *id) const;
974 FLATBUFFERS_CHECKED_ERROR Expect(int t);
975 std::string TokenToStringId(int t) const;
976 EnumDef *LookupEnum(const std::string &id);
977 FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
978 std::string *last);
979 FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
980 FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
981 FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
982 const std::string &name, const Type &type,
983 FieldDef **dest);
984 FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
Austin Schuh272c6132020-11-14 16:37:52 -0800985 FLATBUFFERS_CHECKED_ERROR ParseString(Value &val, bool use_string_pooling);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700986 FLATBUFFERS_CHECKED_ERROR ParseComma();
987 FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
988 size_t parent_fieldn,
989 const StructDef *parent_struct_def,
990 uoffset_t count,
991 bool inside_vector = false);
992 template<typename F>
993 FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
994 const StructDef *struct_def,
995 F body);
996 FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
997 std::string *value, uoffset_t *ovalue);
998 void SerializeStruct(const StructDef &struct_def, const Value &val);
999 void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
1000 const Value &val);
1001 template<typename F>
1002 FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
1003 FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
1004 FieldDef *field, size_t fieldn);
1005 FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
Austin Schuh272c6132020-11-14 16:37:52 -08001006 FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(
1007 Value &val, FieldDef *field, size_t fieldn,
1008 const StructDef *parent_struct_def);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001009 FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
Austin Schuh272c6132020-11-14 16:37:52 -08001010 FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken,
1011 bool check, Value &e, BaseType req,
1012 bool *destmatch);
1013 FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001014 FLATBUFFERS_CHECKED_ERROR TokenError();
Austin Schuh272c6132020-11-14 16:37:52 -08001015 FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e,
1016 bool check_now);
1017 FLATBUFFERS_CHECKED_ERROR ParseFunction(const std::string *name, Value &e);
1018 FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type,
1019 std::string *result);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001020 StructDef *LookupCreateStruct(const std::string &name,
1021 bool create_if_new = true,
1022 bool definition = false);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001023 FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest,
1024 const char *filename);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001025 FLATBUFFERS_CHECKED_ERROR ParseNamespace();
1026 FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
1027 StructDef **dest);
Austin Schuh272c6132020-11-14 16:37:52 -08001028 FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001029 EnumDef **dest);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001030 FLATBUFFERS_CHECKED_ERROR ParseDecl(const char *filename);
1031 FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001032 FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
1033 bool isextend, bool inside_oneof);
James Kuszmaul3b15b0c2022-11-08 14:03:16 -08001034 FLATBUFFERS_CHECKED_ERROR ParseProtoMapField(StructDef *struct_def);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001035 FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
1036 FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
1037 FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
1038 FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
1039 FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
1040 FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001041 FLATBUFFERS_CHECKED_ERROR ParseFlexBufferNumericConstant(
1042 flexbuffers::Builder *builder);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001043 FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
1044 FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
1045 const char *source_filename);
1046 FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
Austin Schuh272c6132020-11-14 16:37:52 -08001047 const char **include_paths,
1048 const char *source_filename);
Austin Schuh2dd86a92022-09-14 21:19:23 -07001049 FLATBUFFERS_CHECKED_ERROR CheckPrivateLeak();
1050 FLATBUFFERS_CHECKED_ERROR CheckPrivatelyLeakedFields(
1051 const Definition &def, const Definition &value_type);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001052 FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
Austin Schuh272c6132020-11-14 16:37:52 -08001053 const char **include_paths,
1054 const char *source_filename,
1055 const char *include_filename);
Austin Schuh58b9b472020-11-25 19:12:44 -08001056 FLATBUFFERS_CHECKED_ERROR DoParseJson();
Austin Schuh272c6132020-11-14 16:37:52 -08001057 FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef *> &fields,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001058 StructDef *struct_def,
Austin Schuh272c6132020-11-14 16:37:52 -08001059 const char *suffix, BaseType baseType);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001060 FLATBUFFERS_CHECKED_ERROR ParseAlignAttribute(
1061 const std::string &align_constant, size_t min_align, size_t *align);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001062
1063 bool SupportsAdvancedUnionFeatures() const;
1064 bool SupportsAdvancedArrayFeatures() const;
Austin Schuh272c6132020-11-14 16:37:52 -08001065 bool SupportsOptionalScalars() const;
James Kuszmaul8e62b022022-03-22 09:33:25 -07001066 bool SupportsDefaultVectorsAndStrings() const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001067 Namespace *UniqueNamespace(Namespace *ns);
1068
1069 FLATBUFFERS_CHECKED_ERROR RecurseError();
1070 template<typename F> CheckedError Recurse(F f);
1071
James Kuszmaul8e62b022022-03-22 09:33:25 -07001072 const std::string &GetPooledString(const std::string &s) const;
1073
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001074 public:
1075 SymbolTable<Type> types_;
1076 SymbolTable<StructDef> structs_;
1077 SymbolTable<EnumDef> enums_;
1078 SymbolTable<ServiceDef> services_;
1079 std::vector<Namespace *> namespaces_;
1080 Namespace *current_namespace_;
1081 Namespace *empty_namespace_;
Austin Schuh272c6132020-11-14 16:37:52 -08001082 std::string error_; // User readable error_ if Parse() == false
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001083
1084 FlatBufferBuilder builder_; // any data contained in the file
Austin Schuh272c6132020-11-14 16:37:52 -08001085 flexbuffers::Builder flex_builder_;
1086 flexbuffers::Reference flex_root_;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001087 StructDef *root_struct_def_;
1088 std::string file_identifier_;
1089 std::string file_extension_;
1090
James Kuszmaul8e62b022022-03-22 09:33:25 -07001091 std::map<uint64_t, std::string> included_files_;
Austin Schuh2dd86a92022-09-14 21:19:23 -07001092 std::map<std::string, std::set<IncludedFile>> files_included_per_file_;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001093 std::vector<std::string> native_included_files_;
1094
1095 std::map<std::string, bool> known_attributes_;
1096
1097 IDLOptions opts;
1098 bool uses_flexbuffers_;
James Kuszmaul8e62b022022-03-22 09:33:25 -07001099 bool has_warning_;
1100
1101 uint64_t advanced_features_;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001102
Austin Schuh2dd86a92022-09-14 21:19:23 -07001103 std::string file_being_parsed_;
1104
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001105 private:
1106 const char *source_;
1107
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001108 std::vector<std::pair<Value, FieldDef *>> field_stack_;
1109
James Kuszmaul8e62b022022-03-22 09:33:25 -07001110 // TODO(cneo): Refactor parser to use string_cache more often to save
1111 // on memory usage.
1112 mutable std::set<std::string> string_cache_;
1113
1114 int anonymous_counter_;
1115 int parse_depth_counter_; // stack-overflow guard
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001116};
1117
1118// Utility functions for multiple generators:
1119
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001120// Generate text (JSON) from a given FlatBuffer, and a given Parser
1121// object that has been populated with the corresponding schema.
1122// If ident_step is 0, no indentation will be generated. Additionally,
1123// if it is less than 0, no linefeeds will be generated either.
1124// See idl_gen_text.cpp.
1125// strict_json adds "quotes" around field names if true.
1126// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
1127// byte arrays in String values), returns false.
Austin Schuh272c6132020-11-14 16:37:52 -08001128extern bool GenerateTextFromTable(const Parser &parser, const void *table,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001129 const std::string &tablename,
1130 std::string *text);
Austin Schuh272c6132020-11-14 16:37:52 -08001131extern bool GenerateText(const Parser &parser, const void *flatbuffer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001132 std::string *text);
Austin Schuh272c6132020-11-14 16:37:52 -08001133extern bool GenerateTextFile(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001134 const std::string &file_name);
1135
Austin Schuh272c6132020-11-14 16:37:52 -08001136// Generate Json schema to string
1137// See idl_gen_json_schema.cpp.
1138extern bool GenerateJsonSchema(const Parser &parser, std::string *json);
1139
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001140// Generate binary files from a given FlatBuffer, and a given Parser
1141// object that has been populated with the corresponding schema.
Austin Schuh272c6132020-11-14 16:37:52 -08001142// See code_generators.cpp.
1143extern bool GenerateBinary(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001144 const std::string &file_name);
1145
1146// Generate a C++ header from the definitions in the Parser object.
1147// See idl_gen_cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001148extern bool GenerateCPP(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001149 const std::string &file_name);
1150
Austin Schuh272c6132020-11-14 16:37:52 -08001151// Generate C# files from the definitions in the Parser object.
1152// See idl_gen_csharp.cpp.
1153extern bool GenerateCSharp(const Parser &parser, const std::string &path,
1154 const std::string &file_name);
1155
1156extern bool GenerateDart(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001157 const std::string &file_name);
1158
Austin Schuh272c6132020-11-14 16:37:52 -08001159// Generate Java files from the definitions in the Parser object.
1160// See idl_gen_java.cpp.
1161extern bool GenerateJava(const Parser &parser, const std::string &path,
1162 const std::string &file_name);
1163
1164// Generate JavaScript or TypeScript code from the definitions in the Parser
1165// object. See idl_gen_js.
James Kuszmaul8e62b022022-03-22 09:33:25 -07001166extern bool GenerateTS(const Parser &parser, const std::string &path,
1167 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001168
1169// Generate Go files from the definitions in the Parser object.
1170// See idl_gen_go.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001171extern bool GenerateGo(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001172 const std::string &file_name);
1173
1174// Generate Php code from the definitions in the Parser object.
1175// See idl_gen_php.
Austin Schuh272c6132020-11-14 16:37:52 -08001176extern bool GeneratePhp(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001177 const std::string &file_name);
1178
1179// Generate Python files from the definitions in the Parser object.
1180// See idl_gen_python.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001181extern bool GeneratePython(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001182 const std::string &file_name);
1183
1184// Generate Lobster files from the definitions in the Parser object.
1185// See idl_gen_lobster.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001186extern bool GenerateLobster(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001187 const std::string &file_name);
1188
1189// Generate Lua files from the definitions in the Parser object.
1190// See idl_gen_lua.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001191extern bool GenerateLua(const Parser &parser, const std::string &path,
1192 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001193
1194// Generate Rust files from the definitions in the Parser object.
1195// See idl_gen_rust.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001196extern bool GenerateRust(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001197 const std::string &file_name);
1198
1199// Generate Json schema file
1200// See idl_gen_json_schema.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001201extern bool GenerateJsonSchema(const Parser &parser, const std::string &path,
1202 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001203
1204extern bool GenerateKotlin(const Parser &parser, const std::string &path,
1205 const std::string &file_name);
1206
Austin Schuh272c6132020-11-14 16:37:52 -08001207// Generate Swift classes.
1208// See idl_gen_swift.cpp
1209extern bool GenerateSwift(const Parser &parser, const std::string &path,
1210 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001211
1212// Generate a schema file from the internal representation, useful after
1213// parsing a .proto schema.
1214extern std::string GenerateFBS(const Parser &parser,
1215 const std::string &file_name);
Austin Schuh272c6132020-11-14 16:37:52 -08001216extern bool GenerateFBS(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001217 const std::string &file_name);
1218
James Kuszmaul8e62b022022-03-22 09:33:25 -07001219// Generate a make rule for the generated TypeScript code.
1220// See idl_gen_ts.cpp.
1221extern std::string TSMakeRule(const Parser &parser, const std::string &path,
1222 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001223
1224// Generate a make rule for the generated C++ header.
1225// See idl_gen_cpp.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001226extern std::string CPPMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001227 const std::string &file_name);
1228
1229// Generate a make rule for the generated Dart code
1230// see idl_gen_dart.cpp
Austin Schuh272c6132020-11-14 16:37:52 -08001231extern std::string DartMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001232 const std::string &file_name);
1233
1234// Generate a make rule for the generated Rust code.
1235// See idl_gen_rust.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001236extern std::string RustMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001237 const std::string &file_name);
1238
Austin Schuh272c6132020-11-14 16:37:52 -08001239// Generate a make rule for generated Java or C# files.
1240// See code_generators.cpp.
James Kuszmaul8e62b022022-03-22 09:33:25 -07001241extern std::string CSharpMakeRule(const Parser &parser, const std::string &path,
1242 const std::string &file_name);
1243extern std::string JavaMakeRule(const Parser &parser, const std::string &path,
1244 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001245
1246// Generate a make rule for the generated text (JSON) files.
1247// See idl_gen_text.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001248extern std::string TextMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001249 const std::string &file_names);
1250
1251// Generate a make rule for the generated binary files.
Austin Schuh272c6132020-11-14 16:37:52 -08001252// See code_generators.cpp.
1253extern std::string BinaryMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001254 const std::string &file_name);
1255
1256// Generate GRPC Cpp interfaces.
1257// See idl_gen_grpc.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001258bool GenerateCppGRPC(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001259 const std::string &file_name);
1260
1261// Generate GRPC Go interfaces.
1262// See idl_gen_grpc.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001263bool GenerateGoGRPC(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001264 const std::string &file_name);
1265
1266// Generate GRPC Java classes.
1267// See idl_gen_grpc.cpp
Austin Schuh272c6132020-11-14 16:37:52 -08001268bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001269 const std::string &file_name);
1270
Austin Schuh272c6132020-11-14 16:37:52 -08001271// Generate GRPC Python interfaces.
1272// See idl_gen_grpc.cpp.
1273bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
1274 const std::string &file_name);
1275
1276// Generate GRPC Swift interfaces.
1277// See idl_gen_grpc.cpp.
1278extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
1279 const std::string &file_name);
1280
1281extern bool GenerateTSGRPC(const Parser &parser, const std::string &path,
James Kuszmaul8e62b022022-03-22 09:33:25 -07001282 const std::string &file_name);
1283
1284extern bool GenerateRustModuleRootFile(const Parser &parser,
1285 const std::string &path);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001286} // namespace flatbuffers
1287
1288#endif // FLATBUFFERS_IDL_H_