blob: 4cfd7ebfb0d9cd346bff78336eab93012f79ab7c [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 Kuszmaul8e62b022022-03-22 09:33:25 -070020#include <functional>
Austin Schuhe89fa2d2019-08-14 20:24:23 -070021#include <map>
22#include <memory>
23#include <stack>
24
25#include "flatbuffers/base.h"
26#include "flatbuffers/flatbuffers.h"
27#include "flatbuffers/flexbuffers.h"
28#include "flatbuffers/hash.h"
29#include "flatbuffers/reflection.h"
30
Austin Schuhe89fa2d2019-08-14 20:24:23 -070031// This file defines the data types representing a parsed IDL (Interface
32// Definition Language) / schema file.
33
34// Limits maximum depth of nested objects.
James Kuszmaul8e62b022022-03-22 09:33:25 -070035// Prevents stack overflow while parse scheme, or json, or flexbuffer.
Austin Schuhe89fa2d2019-08-14 20:24:23 -070036#if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
37# define FLATBUFFERS_MAX_PARSING_DEPTH 64
38#endif
39
40namespace flatbuffers {
41
42// The order of these matters for Is*() functions below.
43// Additionally, Parser::ParseType assumes bool..string is a contiguous range
44// of type tokens.
45// clang-format off
46#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
Austin Schuh272c6132020-11-14 16:37:52 -080047 TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
48 TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) /* begin scalar/int */ \
49 TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool) \
50 TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8) \
51 TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
52 TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16) \
53 TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16) \
54 TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32) \
55 TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32) \
56 TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64) \
57 TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64) /* end int */ \
58 TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32) /* begin float */ \
59 TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double) /* end float/scalar */
Austin Schuhe89fa2d2019-08-14 20:24:23 -070060#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
Austin Schuh272c6132020-11-14 16:37:52 -080061 TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>) \
62 TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>) \
63 TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>) \
64 TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070065#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
Austin Schuh272c6132020-11-14 16:37:52 -080066 TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070067// The fields are:
68// - enum
69// - FlatBuffers schema type.
70// - C++ type.
71// - Java type.
72// - Go type.
73// - C# / .Net type.
74// - Python type.
Austin Schuhe89fa2d2019-08-14 20:24:23 -070075// - Kotlin type.
James Kuszmaul8e62b022022-03-22 09:33:25 -070076// - Rust type.
Austin Schuhe89fa2d2019-08-14 20:24:23 -070077
78// using these macros, we can now write code dealing with types just once, e.g.
79
80/*
81switch (type) {
82 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
83 RTYPE, KTYPE) \
84 case BASE_TYPE_ ## ENUM: \
85 // do something specific to CTYPE here
86 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
87 #undef FLATBUFFERS_TD
88}
89*/
90
Austin Schuh272c6132020-11-14 16:37:52 -080091// If not all FLATBUFFERS_GEN_() arguments are necessary for implementation
92// of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed).
93// In the above example, only CTYPE is used to generate the code, it can be rewritten:
94
95/*
96switch (type) {
97 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
98 case BASE_TYPE_ ## ENUM: \
99 // do something specific to CTYPE here
100 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
101 #undef FLATBUFFERS_TD
102}
103*/
104
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700105#define FLATBUFFERS_GEN_TYPES(TD) \
106 FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
107 FLATBUFFERS_GEN_TYPES_POINTER(TD) \
108 FLATBUFFERS_GEN_TYPE_ARRAY(TD)
109
110// Create an enum for all the types above.
111#ifdef __GNUC__
112__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
113#endif
114enum BaseType {
Austin Schuh272c6132020-11-14 16:37:52 -0800115 #define FLATBUFFERS_TD(ENUM, ...) \
116 BASE_TYPE_ ## ENUM,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700117 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
118 #undef FLATBUFFERS_TD
119};
120
Austin Schuh272c6132020-11-14 16:37:52 -0800121#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
122 static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
123 "define largest_scalar_t as " #CTYPE);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700124 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
125#undef FLATBUFFERS_TD
126
127inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
128 t <= BASE_TYPE_DOUBLE; }
129inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
130 t <= BASE_TYPE_ULONG; }
131inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
132 t == BASE_TYPE_DOUBLE; }
133inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
134 t == BASE_TYPE_ULONG; }
135inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
136inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
137 t <= BASE_TYPE_UCHAR; }
138
139inline bool IsUnsigned(BaseType t) {
140 return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
141 (t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) ||
142 (t == BASE_TYPE_ULONG);
143}
144
145// clang-format on
146
147extern const char *const kTypeNames[];
148extern const char kTypeSizes[];
149
150inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
151
152struct StructDef;
153struct EnumDef;
154class Parser;
155
156// Represents any type in the IDL, which is a combination of the BaseType
157// and additional information for vectors/structs_.
158struct Type {
159 explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
160 EnumDef *_ed = nullptr, uint16_t _fixed_length = 0)
161 : base_type(_base_type),
162 element(BASE_TYPE_NONE),
163 struct_def(_sd),
164 enum_def(_ed),
165 fixed_length(_fixed_length) {}
166
Austin Schuh2dd86a92022-09-14 21:19:23 -0700167 bool operator==(const Type &o) const {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700168 return base_type == o.base_type && element == o.element &&
169 struct_def == o.struct_def && enum_def == o.enum_def;
170 }
171
172 Type VectorType() const {
173 return Type(element, struct_def, enum_def, fixed_length);
174 }
175
176 Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
177
178 bool Deserialize(const Parser &parser, const reflection::Type *type);
179
180 BaseType base_type;
181 BaseType element; // only set if t == BASE_TYPE_VECTOR
182 StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
183 EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
184 // or for an integral type derived from an enum.
185 uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY
186};
187
188// Represents a parsed scalar value, it's type, and field offset.
189struct Value {
190 Value()
191 : constant("0"),
192 offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
193 Type type;
194 std::string constant;
195 voffset_t offset;
196};
197
198// Helper class that retains the original order of a set of identifiers and
199// also provides quick lookup.
200template<typename T> class SymbolTable {
201 public:
202 ~SymbolTable() {
203 for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
204 }
205
206 bool Add(const std::string &name, T *e) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700207 vec.emplace_back(e);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700208 auto it = dict.find(name);
209 if (it != dict.end()) return true;
210 dict[name] = e;
211 return false;
212 }
213
214 void Move(const std::string &oldname, const std::string &newname) {
215 auto it = dict.find(oldname);
216 if (it != dict.end()) {
217 auto obj = it->second;
218 dict.erase(it);
219 dict[newname] = obj;
220 } else {
221 FLATBUFFERS_ASSERT(false);
222 }
223 }
224
225 T *Lookup(const std::string &name) const {
226 auto it = dict.find(name);
227 return it == dict.end() ? nullptr : it->second;
228 }
229
230 public:
231 std::map<std::string, T *> dict; // quick lookup
232 std::vector<T *> vec; // Used to iterate in order of insertion
233};
234
235// A name space, as set in the schema.
236struct Namespace {
237 Namespace() : from_table(0) {}
238
Austin Schuh272c6132020-11-14 16:37:52 -0800239 // Given a (potentially unqualified) name, return the "fully qualified" name
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700240 // which has a full namespaced descriptor.
241 // With max_components you can request less than the number of components
242 // the current namespace has.
243 std::string GetFullyQualifiedName(const std::string &name,
244 size_t max_components = 1000) const;
245
246 std::vector<std::string> components;
247 size_t from_table; // Part of the namespace corresponds to a message/table.
248};
249
250inline bool operator<(const Namespace &a, const Namespace &b) {
251 size_t min_size = std::min(a.components.size(), b.components.size());
252 for (size_t i = 0; i < min_size; ++i) {
253 if (a.components[i] != b.components[i])
254 return a.components[i] < b.components[i];
255 }
256 return a.components.size() < b.components.size();
257}
258
259// Base class for all definition types (fields, structs_, enums_).
260struct Definition {
261 Definition()
262 : generated(false),
263 defined_namespace(nullptr),
264 serialized_location(0),
265 index(-1),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700266 refcount(1),
267 declaration_file(nullptr) {}
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700268
269 flatbuffers::Offset<
270 flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
271 SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
272
273 bool DeserializeAttributes(Parser &parser,
274 const Vector<Offset<reflection::KeyValue>> *attrs);
275
276 std::string name;
277 std::string file;
278 std::vector<std::string> doc_comment;
279 SymbolTable<Value> attributes;
280 bool generated; // did we already output code for this definition?
281 Namespace *defined_namespace; // Where it was defined.
282
283 // For use with Serialize()
284 uoffset_t serialized_location;
285 int index; // Inside the vector it is stored.
286 int refcount;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700287 const std::string *declaration_file;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700288};
289
290struct FieldDef : public Definition {
291 FieldDef()
292 : deprecated(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700293 key(false),
294 shared(false),
295 native_inline(false),
296 flexbuffer(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700297 presence(kDefault),
Austin Schuh2dd86a92022-09-14 21:19:23 -0700298 nested_flatbuffer(nullptr),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700299 padding(0) {}
300
301 Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
302 const Parser &parser) const;
303
304 bool Deserialize(Parser &parser, const reflection::Field *field);
305
Austin Schuh272c6132020-11-14 16:37:52 -0800306 bool IsScalarOptional() const {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700307 return IsScalar(value.type.base_type) && IsOptional();
Austin Schuh272c6132020-11-14 16:37:52 -0800308 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700309 bool IsOptional() const { return presence == kOptional; }
310 bool IsRequired() const { return presence == kRequired; }
311 bool IsDefault() const { return presence == kDefault; }
Austin Schuh272c6132020-11-14 16:37:52 -0800312
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700313 Value value;
314 bool deprecated; // Field is allowed to be present in old data, but can't be.
315 // written in new data nor accessed in new code.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700316 bool key; // Field functions as a key for creating sorted vectors.
317 bool shared; // Field will be using string pooling (i.e. CreateSharedString)
318 // as default serialization behavior if field is a string.
319 bool native_inline; // Field will be defined inline (instead of as a pointer)
320 // for native tables if field is a struct.
321 bool flexbuffer; // This field contains FlexBuffer data.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700322
323 enum Presence {
324 // Field must always be present.
325 kRequired,
326 // Non-presence should be signalled to and controlled by users.
327 kOptional,
328 // Non-presence is hidden from users.
329 // Implementations may omit writing default values.
330 kDefault,
331 };
332 Presence static MakeFieldPresence(bool optional, bool required) {
333 FLATBUFFERS_ASSERT(!(required && optional));
334 // clang-format off
335 return required ? FieldDef::kRequired
336 : optional ? FieldDef::kOptional
337 : FieldDef::kDefault;
338 // clang-format on
339 }
340 Presence presence;
341
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700342 StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
343 size_t padding; // Bytes to always pad after this field.
344};
345
346struct StructDef : public Definition {
347 StructDef()
348 : fixed(false),
349 predecl(true),
350 sortbysize(true),
351 has_key(false),
352 minalign(1),
353 bytesize(0) {}
354
355 void PadLastField(size_t min_align) {
356 auto padding = PaddingBytes(bytesize, min_align);
357 bytesize += padding;
358 if (fields.vec.size()) fields.vec.back()->padding = padding;
359 }
360
361 Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
362 const Parser &parser) const;
363
364 bool Deserialize(Parser &parser, const reflection::Object *object);
365
366 SymbolTable<FieldDef> fields;
367
368 bool fixed; // If it's struct, not a table.
369 bool predecl; // If it's used before it was defined.
370 bool sortbysize; // Whether fields come in the declaration or size order.
371 bool has_key; // It has a key field.
372 size_t minalign; // What the whole object needs to be aligned to.
373 size_t bytesize; // Size if fixed.
374
375 flatbuffers::unique_ptr<std::string> original_location;
376};
377
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700378struct EnumDef;
379struct EnumValBuilder;
380
381struct EnumVal {
Austin Schuh272c6132020-11-14 16:37:52 -0800382 Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
383 const Parser &parser) const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700384
385 bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
386
387 uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
388 int64_t GetAsInt64() const { return value; }
389 bool IsZero() const { return 0 == value; }
390 bool IsNonZero() const { return !IsZero(); }
391
392 std::string name;
393 std::vector<std::string> doc_comment;
394 Type union_type;
395
396 private:
397 friend EnumDef;
398 friend EnumValBuilder;
399 friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
400
401 EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
402 EnumVal() : value(0) {}
403
404 int64_t value;
405};
406
407struct EnumDef : public Definition {
408 EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
409
410 Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
411 const Parser &parser) const;
412
413 bool Deserialize(Parser &parser, const reflection::Enum *values);
414
415 template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
416 void SortByValue();
417 void RemoveDuplicates();
418
419 std::string AllFlags() const;
420 const EnumVal *MinValue() const;
421 const EnumVal *MaxValue() const;
422 // Returns the number of integer steps from v1 to v2.
423 uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
424 // Returns the number of integer steps from Min to Max.
425 uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
426
427 EnumVal *ReverseLookup(int64_t enum_idx,
428 bool skip_union_default = false) const;
429 EnumVal *FindByValue(const std::string &constant) const;
430
431 std::string ToString(const EnumVal &ev) const {
432 return IsUInt64() ? NumToString(ev.GetAsUInt64())
433 : NumToString(ev.GetAsInt64());
434 }
435
436 size_t size() const { return vals.vec.size(); }
437
Austin Schuh272c6132020-11-14 16:37:52 -0800438 const std::vector<EnumVal *> &Vals() const { return vals.vec; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700439
440 const EnumVal *Lookup(const std::string &enum_name) const {
441 return vals.Lookup(enum_name);
442 }
443
444 bool is_union;
445 // Type is a union which uses type aliases where at least one type is
446 // available under two different names.
447 bool uses_multiple_type_instances;
448 Type underlying_type;
449
450 private:
451 bool IsUInt64() const {
452 return (BASE_TYPE_ULONG == underlying_type.base_type);
453 }
454
455 friend EnumValBuilder;
456 SymbolTable<EnumVal> vals;
457};
458
Austin Schuh272c6132020-11-14 16:37:52 -0800459inline bool IsString(const Type &type) {
460 return type.base_type == BASE_TYPE_STRING;
461}
462
463inline bool IsStruct(const Type &type) {
464 return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
465}
466
Austin Schuh2dd86a92022-09-14 21:19:23 -0700467inline bool IsTable(const Type &type) {
468 return type.base_type == BASE_TYPE_STRUCT && !type.struct_def->fixed;
469}
470
Austin Schuh272c6132020-11-14 16:37:52 -0800471inline bool IsUnion(const Type &type) {
472 return type.enum_def != nullptr && type.enum_def->is_union;
473}
474
James Kuszmaul8e62b022022-03-22 09:33:25 -0700475inline bool IsUnionType(const Type &type) {
476 return IsUnion(type) && IsInteger(type.base_type);
477}
478
Austin Schuh272c6132020-11-14 16:37:52 -0800479inline bool IsVector(const Type &type) {
480 return type.base_type == BASE_TYPE_VECTOR;
481}
482
Austin Schuh2dd86a92022-09-14 21:19:23 -0700483inline bool IsVectorOfStruct(const Type& type) {
484 return IsVector(type) && IsStruct(type.VectorType());
485}
486
487inline bool IsVectorOfTable(const Type& type) {
488 return IsVector(type) && IsTable(type.VectorType());
489}
490
Austin Schuh272c6132020-11-14 16:37:52 -0800491inline bool IsArray(const Type &type) {
492 return type.base_type == BASE_TYPE_ARRAY;
493}
494
495inline bool IsSeries(const Type &type) {
496 return IsVector(type) || IsArray(type);
497}
498
499inline bool IsEnum(const Type &type) {
500 return type.enum_def != nullptr && IsInteger(type.base_type);
501}
502
503inline size_t InlineSize(const Type &type) {
504 return IsStruct(type)
505 ? type.struct_def->bytesize
506 : (IsArray(type)
507 ? InlineSize(type.VectorType()) * type.fixed_length
508 : SizeOf(type.base_type));
509}
510
511inline size_t InlineAlignment(const Type &type) {
512 if (IsStruct(type)) {
513 return type.struct_def->minalign;
514 } else if (IsArray(type)) {
515 return IsStruct(type.VectorType()) ? type.struct_def->minalign
516 : SizeOf(type.element);
517 } else {
518 return SizeOf(type.base_type);
519 }
520}
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700521inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) {
522 return lhs.value == rhs.value;
523}
524inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
525 return !(lhs == rhs);
526}
527
528inline bool EqualByName(const Type &a, const Type &b) {
529 return a.base_type == b.base_type && a.element == b.element &&
530 (a.struct_def == b.struct_def ||
531 a.struct_def->name == b.struct_def->name) &&
532 (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
533}
534
535struct RPCCall : public Definition {
Austin Schuh272c6132020-11-14 16:37:52 -0800536 Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder,
537 const Parser &parser) const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700538
539 bool Deserialize(Parser &parser, const reflection::RPCCall *call);
540
541 StructDef *request, *response;
542};
543
544struct ServiceDef : public Definition {
Austin Schuh272c6132020-11-14 16:37:52 -0800545 Offset<reflection::Service> Serialize(FlatBufferBuilder *builder,
546 const Parser &parser) const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700547 bool Deserialize(Parser &parser, const reflection::Service *service);
548
549 SymbolTable<RPCCall> calls;
550};
551
Austin Schuh2dd86a92022-09-14 21:19:23 -0700552struct IncludedFile {
553 // The name of the schema file being included, as defined in the .fbs file.
554 // This includes the prefix (e.g., include "foo/bar/baz.fbs" would mean this
555 // value is "foo/bar/baz.fbs").
556 std::string schema_name;
557
558 // The filename of where the included file was found, after searching the
559 // relative paths plus any other paths included with `flatc -I ...`. Note,
560 // while this is sometimes the same as schema_name, it is not always, since it
561 // can be defined relative to where flatc was invoked.
562 std::string filename;
563};
564
565// Since IncludedFile is contained within a std::set, need to provide ordering.
566inline bool operator<(const IncludedFile &a, const IncludedFile &b) {
567 return a.filename < b.filename;
568}
569
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700570// Container of options that may apply to any of the source/text generators.
571struct IDLOptions {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700572 // field case style options for C++
573 enum CaseStyle { CaseStyle_Unchanged = 0, CaseStyle_Upper, CaseStyle_Lower };
574
Austin Schuh272c6132020-11-14 16:37:52 -0800575 bool gen_jvmstatic;
576 // Use flexbuffers instead for binary and text generation
577 bool use_flexbuffers;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700578 bool strict_json;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700579 bool output_default_scalars_in_json;
580 int indent_step;
581 bool output_enum_identifiers;
582 bool prefixed_enums;
583 bool scoped_enums;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700584 bool swift_implementation_only;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700585 bool include_dependence_headers;
586 bool mutable_buffer;
587 bool one_file;
588 bool proto_mode;
589 bool proto_oneof_union;
590 bool generate_all;
591 bool skip_unexpected_fields_in_json;
592 bool generate_name_strings;
593 bool generate_object_based_api;
594 bool gen_compare;
595 std::string cpp_object_api_pointer_type;
596 std::string cpp_object_api_string_type;
597 bool cpp_object_api_string_flexible_constructor;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700598 CaseStyle cpp_object_api_field_case_style;
Austin Schuh272c6132020-11-14 16:37:52 -0800599 bool cpp_direct_copy;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700600 bool gen_nullable;
Austin Schuh272c6132020-11-14 16:37:52 -0800601 bool java_checkerframework;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700602 bool gen_generated;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700603 bool gen_json_coders;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700604 std::string object_prefix;
605 std::string object_suffix;
606 bool union_value_namespacing;
607 bool allow_non_utf8;
608 bool natural_utf8;
609 std::string include_prefix;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700610 bool keep_prefix;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700611 bool binary_schema_comments;
612 bool binary_schema_builtins;
Austin Schuh272c6132020-11-14 16:37:52 -0800613 bool binary_schema_gen_embed;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700614 std::string go_import;
615 std::string go_namespace;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700616 bool protobuf_ascii_alike;
617 bool size_prefixed;
618 std::string root_type;
619 bool force_defaults;
Austin Schuh272c6132020-11-14 16:37:52 -0800620 bool java_primitive_has_method;
621 bool cs_gen_json_serializer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700622 std::vector<std::string> cpp_includes;
Austin Schuh272c6132020-11-14 16:37:52 -0800623 std::string cpp_std;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700624 bool cpp_static_reflection;
Austin Schuh272c6132020-11-14 16:37:52 -0800625 std::string proto_namespace_suffix;
626 std::string filename_suffix;
627 std::string filename_extension;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700628 bool no_warnings;
629 bool warnings_as_errors;
630 std::string project_root;
631 bool cs_global_alias;
632 bool json_nested_flatbuffers;
633 bool json_nested_flexbuffers;
634 bool json_nested_legacy_flatbuffers;
635 bool ts_flat_file;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700636 bool no_leak_private_annotations;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700637
638 // Possible options for the more general generator below.
639 enum Language {
640 kJava = 1 << 0,
641 kCSharp = 1 << 1,
642 kGo = 1 << 2,
643 kCpp = 1 << 3,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700644 kPython = 1 << 5,
645 kPhp = 1 << 6,
646 kJson = 1 << 7,
647 kBinary = 1 << 8,
648 kTs = 1 << 9,
649 kJsonSchema = 1 << 10,
650 kDart = 1 << 11,
651 kLua = 1 << 12,
652 kLobster = 1 << 13,
653 kRust = 1 << 14,
654 kKotlin = 1 << 15,
Austin Schuh272c6132020-11-14 16:37:52 -0800655 kSwift = 1 << 16,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700656 kMAX
657 };
658
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700659 enum MiniReflect { kNone, kTypes, kTypesAndNames };
660
661 MiniReflect mini_reflect;
662
Austin Schuh58b9b472020-11-25 19:12:44 -0800663 // If set, require all fields in a table to be explicitly numbered.
664 bool require_explicit_ids;
665
James Kuszmaul8e62b022022-03-22 09:33:25 -0700666 // If set, implement serde::Serialize for generated Rust types
667 bool rust_serialize;
668
669 // If set, generate rust types in individual files with a root module file.
670 bool rust_module_root_file;
671
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700672 // The corresponding language bit will be set if a language is included
673 // for code generation.
674 unsigned long lang_to_generate;
675
Austin Schuh272c6132020-11-14 16:37:52 -0800676 // If set (default behavior), empty string fields will be set to nullptr to
677 // make the flatbuffer more compact.
678 bool set_empty_strings_to_null;
679
680 // If set (default behavior), empty vector fields will be set to nullptr to
681 // make the flatbuffer more compact.
682 bool set_empty_vectors_to_null;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700683
684 IDLOptions()
Austin Schuh272c6132020-11-14 16:37:52 -0800685 : gen_jvmstatic(false),
686 use_flexbuffers(false),
687 strict_json(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700688 output_default_scalars_in_json(false),
689 indent_step(2),
690 output_enum_identifiers(true),
691 prefixed_enums(true),
692 scoped_enums(false),
Austin Schuh2dd86a92022-09-14 21:19:23 -0700693 swift_implementation_only(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700694 include_dependence_headers(true),
695 mutable_buffer(false),
696 one_file(false),
697 proto_mode(false),
698 proto_oneof_union(false),
699 generate_all(false),
700 skip_unexpected_fields_in_json(false),
701 generate_name_strings(false),
702 generate_object_based_api(false),
703 gen_compare(false),
704 cpp_object_api_pointer_type("std::unique_ptr"),
705 cpp_object_api_string_flexible_constructor(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700706 cpp_object_api_field_case_style(CaseStyle_Unchanged),
Austin Schuh272c6132020-11-14 16:37:52 -0800707 cpp_direct_copy(true),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700708 gen_nullable(false),
Austin Schuh272c6132020-11-14 16:37:52 -0800709 java_checkerframework(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700710 gen_generated(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700711 gen_json_coders(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700712 object_suffix("T"),
713 union_value_namespacing(true),
714 allow_non_utf8(false),
715 natural_utf8(false),
Austin Schuh2dd86a92022-09-14 21:19:23 -0700716 keep_prefix(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700717 binary_schema_comments(false),
718 binary_schema_builtins(false),
Austin Schuh272c6132020-11-14 16:37:52 -0800719 binary_schema_gen_embed(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700720 protobuf_ascii_alike(false),
721 size_prefixed(false),
722 force_defaults(false),
Austin Schuh272c6132020-11-14 16:37:52 -0800723 java_primitive_has_method(false),
724 cs_gen_json_serializer(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700725 cpp_static_reflection(false),
Austin Schuh272c6132020-11-14 16:37:52 -0800726 filename_suffix("_generated"),
727 filename_extension(),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700728 no_warnings(false),
729 warnings_as_errors(false),
730 project_root(""),
731 cs_global_alias(false),
732 json_nested_flatbuffers(true),
733 json_nested_flexbuffers(true),
734 json_nested_legacy_flatbuffers(false),
735 ts_flat_file(false),
Austin Schuh2dd86a92022-09-14 21:19:23 -0700736 no_leak_private_annotations(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700737 mini_reflect(IDLOptions::kNone),
Austin Schuh58b9b472020-11-25 19:12:44 -0800738 require_explicit_ids(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700739 rust_serialize(false),
740 rust_module_root_file(false),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700741 lang_to_generate(0),
Austin Schuh272c6132020-11-14 16:37:52 -0800742 set_empty_strings_to_null(true),
743 set_empty_vectors_to_null(true) {}
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700744};
745
746// This encapsulates where the parser is in the current source file.
747struct ParserState {
748 ParserState()
749 : cursor_(nullptr),
750 line_start_(nullptr),
751 line_(0),
752 token_(-1),
753 attr_is_trivial_ascii_string_(true) {}
754
755 protected:
756 void ResetState(const char *source) {
757 cursor_ = source;
758 line_ = 0;
759 MarkNewLine();
760 }
761
762 void MarkNewLine() {
763 line_start_ = cursor_;
764 line_ += 1;
765 }
766
767 int64_t CursorPosition() const {
768 FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
769 return static_cast<int64_t>(cursor_ - line_start_);
770 }
771
772 const char *cursor_;
773 const char *line_start_;
774 int line_; // the current line being parsed
775 int token_;
776
777 // Flag: text in attribute_ is true ASCII string without escape
778 // sequences. Only printable ASCII (without [\t\r\n]).
779 // Used for number-in-string (and base64 string in future).
780 bool attr_is_trivial_ascii_string_;
781 std::string attribute_;
782 std::vector<std::string> doc_comment_;
783};
784
785// A way to make error propagation less error prone by requiring values to be
786// checked.
787// Once you create a value of this type you must either:
788// - Call Check() on it.
789// - Copy or assign it to another value.
790// Failure to do so leads to an assert.
791// This guarantees that this as return value cannot be ignored.
792class CheckedError {
793 public:
794 explicit CheckedError(bool error)
795 : is_error_(error), has_been_checked_(false) {}
796
797 CheckedError &operator=(const CheckedError &other) {
798 is_error_ = other.is_error_;
799 has_been_checked_ = false;
800 other.has_been_checked_ = true;
801 return *this;
802 }
803
804 CheckedError(const CheckedError &other) {
805 *this = other; // Use assignment operator.
806 }
807
808 ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
809
810 bool Check() {
811 has_been_checked_ = true;
812 return is_error_;
813 }
814
815 private:
816 bool is_error_;
817 mutable bool has_been_checked_;
818};
819
820// Additionally, in GCC we can get these errors statically, for additional
821// assurance:
822// clang-format off
823#ifdef __GNUC__
824#define FLATBUFFERS_CHECKED_ERROR CheckedError \
825 __attribute__((warn_unused_result))
826#else
827#define FLATBUFFERS_CHECKED_ERROR CheckedError
828#endif
829// clang-format on
830
831class Parser : public ParserState {
832 public:
833 explicit Parser(const IDLOptions &options = IDLOptions())
834 : current_namespace_(nullptr),
835 empty_namespace_(nullptr),
Austin Schuh272c6132020-11-14 16:37:52 -0800836 flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700837 root_struct_def_(nullptr),
838 opts(options),
839 uses_flexbuffers_(false),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700840 has_warning_(false),
841 advanced_features_(0),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700842 source_(nullptr),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700843 anonymous_counter_(0),
844 parse_depth_counter_(0) {
Austin Schuh272c6132020-11-14 16:37:52 -0800845 if (opts.force_defaults) { builder_.ForceDefaults(true); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700846 // Start out with the empty namespace being current.
847 empty_namespace_ = new Namespace();
848 namespaces_.push_back(empty_namespace_);
849 current_namespace_ = empty_namespace_;
850 known_attributes_["deprecated"] = true;
851 known_attributes_["required"] = true;
852 known_attributes_["key"] = true;
853 known_attributes_["shared"] = true;
854 known_attributes_["hash"] = true;
855 known_attributes_["id"] = true;
856 known_attributes_["force_align"] = true;
857 known_attributes_["bit_flags"] = true;
858 known_attributes_["original_order"] = true;
859 known_attributes_["nested_flatbuffer"] = true;
860 known_attributes_["csharp_partial"] = true;
861 known_attributes_["streaming"] = true;
862 known_attributes_["idempotent"] = true;
863 known_attributes_["cpp_type"] = true;
864 known_attributes_["cpp_ptr_type"] = true;
865 known_attributes_["cpp_ptr_type_get"] = true;
866 known_attributes_["cpp_str_type"] = true;
867 known_attributes_["cpp_str_flex_ctor"] = true;
868 known_attributes_["native_inline"] = true;
869 known_attributes_["native_custom_alloc"] = true;
870 known_attributes_["native_type"] = true;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700871 known_attributes_["native_type_pack_name"] = true;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700872 known_attributes_["native_default"] = true;
873 known_attributes_["flexbuffer"] = true;
874 known_attributes_["private"] = true;
875 }
876
877 ~Parser() {
878 for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
879 delete *it;
880 }
881 }
882
883 // Parse the string containing either schema or JSON data, which will
884 // populate the SymbolTable's or the FlatBufferBuilder above.
885 // include_paths is used to resolve any include statements, and typically
886 // should at least include the project path (where you loaded source_ from).
887 // include_paths must be nullptr terminated if specified.
888 // If include_paths is nullptr, it will attempt to load from the current
889 // directory.
890 // If the source was loaded from a file and isn't an include file,
891 // supply its name in source_filename.
892 // All paths specified in this call must be in posix format, if you accept
893 // paths from user input, please call PosixPath on them first.
894 bool Parse(const char *_source, const char **include_paths = nullptr,
895 const char *source_filename = nullptr);
896
Austin Schuh58b9b472020-11-25 19:12:44 -0800897 bool ParseJson(const char *json, const char *json_filename = nullptr);
898
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700899 // Set the root type. May override the one set in the schema.
900 bool SetRootType(const char *name);
901
902 // Mark all definitions as already having code generated.
903 void MarkGenerated();
904
905 // Get the files recursively included by the given file. The returned
906 // container will have at least the given file.
907 std::set<std::string> GetIncludedFilesRecursive(
908 const std::string &file_name) const;
909
910 // Fills builder_ with a binary version of the schema parsed.
911 // See reflection/reflection.fbs
912 void Serialize();
913
914 // Deserialize a schema buffer
915 bool Deserialize(const uint8_t *buf, const size_t size);
916
917 // Fills internal structure as if the schema passed had been loaded by parsing
918 // with Parse except that included filenames will not be populated.
Austin Schuh272c6132020-11-14 16:37:52 -0800919 bool Deserialize(const reflection::Schema *schema);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700920
Austin Schuh272c6132020-11-14 16:37:52 -0800921 Type *DeserializeType(const reflection::Type *type);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700922
923 // Checks that the schema represented by this parser is a safe evolution
924 // of the schema provided. Returns non-empty error on any problems.
925 std::string ConformTo(const Parser &base);
926
927 // Similar to Parse(), but now only accepts JSON to be parsed into a
928 // FlexBuffer.
929 bool ParseFlexBuffer(const char *source, const char *source_filename,
930 flexbuffers::Builder *builder);
931
932 StructDef *LookupStruct(const std::string &id) const;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700933 StructDef *LookupStructThruParentNamespaces(const std::string &id) const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700934
935 std::string UnqualifiedName(const std::string &fullQualifiedName);
936
937 FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
938
Austin Schuh272c6132020-11-14 16:37:52 -0800939 // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars
940 // in a schema.
941 // @param opts Options used to parce a schema and generate code.
942 static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts);
943
Austin Schuh2dd86a92022-09-14 21:19:23 -0700944 // Get the set of included files that are directly referenced by the file
945 // being parsed. This does not include files that are transitively included by
946 // others includes.
947 std::vector<IncludedFile> GetIncludedFiles() const;
948
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700949 private:
James Kuszmaul8e62b022022-03-22 09:33:25 -0700950 class ParseDepthGuard;
951
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700952 void Message(const std::string &msg);
953 void Warning(const std::string &msg);
954 FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
955 FLATBUFFERS_CHECKED_ERROR Next();
956 FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
957 bool Is(int t) const;
958 bool IsIdent(const char *id) const;
959 FLATBUFFERS_CHECKED_ERROR Expect(int t);
960 std::string TokenToStringId(int t) const;
961 EnumDef *LookupEnum(const std::string &id);
962 FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
963 std::string *last);
964 FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
965 FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
966 FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
967 const std::string &name, const Type &type,
968 FieldDef **dest);
969 FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
Austin Schuh272c6132020-11-14 16:37:52 -0800970 FLATBUFFERS_CHECKED_ERROR ParseString(Value &val, bool use_string_pooling);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700971 FLATBUFFERS_CHECKED_ERROR ParseComma();
972 FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
973 size_t parent_fieldn,
974 const StructDef *parent_struct_def,
975 uoffset_t count,
976 bool inside_vector = false);
977 template<typename F>
978 FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
979 const StructDef *struct_def,
980 F body);
981 FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
982 std::string *value, uoffset_t *ovalue);
983 void SerializeStruct(const StructDef &struct_def, const Value &val);
984 void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
985 const Value &val);
986 template<typename F>
987 FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
988 FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
989 FieldDef *field, size_t fieldn);
990 FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
Austin Schuh272c6132020-11-14 16:37:52 -0800991 FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(
992 Value &val, FieldDef *field, size_t fieldn,
993 const StructDef *parent_struct_def);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700994 FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
Austin Schuh272c6132020-11-14 16:37:52 -0800995 FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken,
996 bool check, Value &e, BaseType req,
997 bool *destmatch);
998 FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700999 FLATBUFFERS_CHECKED_ERROR TokenError();
Austin Schuh272c6132020-11-14 16:37:52 -08001000 FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e,
1001 bool check_now);
1002 FLATBUFFERS_CHECKED_ERROR ParseFunction(const std::string *name, Value &e);
1003 FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type,
1004 std::string *result);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001005 StructDef *LookupCreateStruct(const std::string &name,
1006 bool create_if_new = true,
1007 bool definition = false);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001008 FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest,
1009 const char *filename);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001010 FLATBUFFERS_CHECKED_ERROR ParseNamespace();
1011 FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
1012 StructDef **dest);
Austin Schuh272c6132020-11-14 16:37:52 -08001013 FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001014 EnumDef **dest);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001015 FLATBUFFERS_CHECKED_ERROR ParseDecl(const char *filename);
1016 FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001017 FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
1018 bool isextend, bool inside_oneof);
1019 FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
1020 FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
1021 FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
1022 FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
1023 FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
1024 FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001025 FLATBUFFERS_CHECKED_ERROR ParseFlexBufferNumericConstant(
1026 flexbuffers::Builder *builder);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001027 FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
1028 FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
1029 const char *source_filename);
1030 FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
Austin Schuh272c6132020-11-14 16:37:52 -08001031 const char **include_paths,
1032 const char *source_filename);
Austin Schuh2dd86a92022-09-14 21:19:23 -07001033 FLATBUFFERS_CHECKED_ERROR CheckPrivateLeak();
1034 FLATBUFFERS_CHECKED_ERROR CheckPrivatelyLeakedFields(
1035 const Definition &def, const Definition &value_type);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001036 FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
Austin Schuh272c6132020-11-14 16:37:52 -08001037 const char **include_paths,
1038 const char *source_filename,
1039 const char *include_filename);
Austin Schuh58b9b472020-11-25 19:12:44 -08001040 FLATBUFFERS_CHECKED_ERROR DoParseJson();
Austin Schuh272c6132020-11-14 16:37:52 -08001041 FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef *> &fields,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001042 StructDef *struct_def,
Austin Schuh272c6132020-11-14 16:37:52 -08001043 const char *suffix, BaseType baseType);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001044 FLATBUFFERS_CHECKED_ERROR ParseAlignAttribute(
1045 const std::string &align_constant, size_t min_align, size_t *align);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001046
1047 bool SupportsAdvancedUnionFeatures() const;
1048 bool SupportsAdvancedArrayFeatures() const;
Austin Schuh272c6132020-11-14 16:37:52 -08001049 bool SupportsOptionalScalars() const;
James Kuszmaul8e62b022022-03-22 09:33:25 -07001050 bool SupportsDefaultVectorsAndStrings() const;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001051 Namespace *UniqueNamespace(Namespace *ns);
1052
1053 FLATBUFFERS_CHECKED_ERROR RecurseError();
1054 template<typename F> CheckedError Recurse(F f);
1055
James Kuszmaul8e62b022022-03-22 09:33:25 -07001056 const std::string &GetPooledString(const std::string &s) const;
1057
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001058 public:
1059 SymbolTable<Type> types_;
1060 SymbolTable<StructDef> structs_;
1061 SymbolTable<EnumDef> enums_;
1062 SymbolTable<ServiceDef> services_;
1063 std::vector<Namespace *> namespaces_;
1064 Namespace *current_namespace_;
1065 Namespace *empty_namespace_;
Austin Schuh272c6132020-11-14 16:37:52 -08001066 std::string error_; // User readable error_ if Parse() == false
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001067
1068 FlatBufferBuilder builder_; // any data contained in the file
Austin Schuh272c6132020-11-14 16:37:52 -08001069 flexbuffers::Builder flex_builder_;
1070 flexbuffers::Reference flex_root_;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001071 StructDef *root_struct_def_;
1072 std::string file_identifier_;
1073 std::string file_extension_;
1074
James Kuszmaul8e62b022022-03-22 09:33:25 -07001075 std::map<uint64_t, std::string> included_files_;
Austin Schuh2dd86a92022-09-14 21:19:23 -07001076 std::map<std::string, std::set<IncludedFile>> files_included_per_file_;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001077 std::vector<std::string> native_included_files_;
1078
1079 std::map<std::string, bool> known_attributes_;
1080
1081 IDLOptions opts;
1082 bool uses_flexbuffers_;
James Kuszmaul8e62b022022-03-22 09:33:25 -07001083 bool has_warning_;
1084
1085 uint64_t advanced_features_;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001086
Austin Schuh2dd86a92022-09-14 21:19:23 -07001087 std::string file_being_parsed_;
1088
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001089 private:
1090 const char *source_;
1091
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001092 std::vector<std::pair<Value, FieldDef *>> field_stack_;
1093
James Kuszmaul8e62b022022-03-22 09:33:25 -07001094 // TODO(cneo): Refactor parser to use string_cache more often to save
1095 // on memory usage.
1096 mutable std::set<std::string> string_cache_;
1097
1098 int anonymous_counter_;
1099 int parse_depth_counter_; // stack-overflow guard
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001100};
1101
1102// Utility functions for multiple generators:
1103
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001104// Generate text (JSON) from a given FlatBuffer, and a given Parser
1105// object that has been populated with the corresponding schema.
1106// If ident_step is 0, no indentation will be generated. Additionally,
1107// if it is less than 0, no linefeeds will be generated either.
1108// See idl_gen_text.cpp.
1109// strict_json adds "quotes" around field names if true.
1110// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
1111// byte arrays in String values), returns false.
Austin Schuh272c6132020-11-14 16:37:52 -08001112extern bool GenerateTextFromTable(const Parser &parser, const void *table,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001113 const std::string &tablename,
1114 std::string *text);
Austin Schuh272c6132020-11-14 16:37:52 -08001115extern bool GenerateText(const Parser &parser, const void *flatbuffer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001116 std::string *text);
Austin Schuh272c6132020-11-14 16:37:52 -08001117extern bool GenerateTextFile(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001118 const std::string &file_name);
1119
Austin Schuh272c6132020-11-14 16:37:52 -08001120// Generate Json schema to string
1121// See idl_gen_json_schema.cpp.
1122extern bool GenerateJsonSchema(const Parser &parser, std::string *json);
1123
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001124// Generate binary files from a given FlatBuffer, and a given Parser
1125// object that has been populated with the corresponding schema.
Austin Schuh272c6132020-11-14 16:37:52 -08001126// See code_generators.cpp.
1127extern bool GenerateBinary(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001128 const std::string &file_name);
1129
1130// Generate a C++ header from the definitions in the Parser object.
1131// See idl_gen_cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001132extern bool GenerateCPP(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001133 const std::string &file_name);
1134
Austin Schuh272c6132020-11-14 16:37:52 -08001135// Generate C# files from the definitions in the Parser object.
1136// See idl_gen_csharp.cpp.
1137extern bool GenerateCSharp(const Parser &parser, const std::string &path,
1138 const std::string &file_name);
1139
1140extern bool GenerateDart(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001141 const std::string &file_name);
1142
Austin Schuh272c6132020-11-14 16:37:52 -08001143// Generate Java files from the definitions in the Parser object.
1144// See idl_gen_java.cpp.
1145extern bool GenerateJava(const Parser &parser, const std::string &path,
1146 const std::string &file_name);
1147
1148// Generate JavaScript or TypeScript code from the definitions in the Parser
1149// object. See idl_gen_js.
James Kuszmaul8e62b022022-03-22 09:33:25 -07001150extern bool GenerateTS(const Parser &parser, const std::string &path,
1151 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001152
1153// Generate Go files from the definitions in the Parser object.
1154// See idl_gen_go.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001155extern bool GenerateGo(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001156 const std::string &file_name);
1157
1158// Generate Php code from the definitions in the Parser object.
1159// See idl_gen_php.
Austin Schuh272c6132020-11-14 16:37:52 -08001160extern bool GeneratePhp(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001161 const std::string &file_name);
1162
1163// Generate Python files from the definitions in the Parser object.
1164// See idl_gen_python.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001165extern bool GeneratePython(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001166 const std::string &file_name);
1167
1168// Generate Lobster files from the definitions in the Parser object.
1169// See idl_gen_lobster.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001170extern bool GenerateLobster(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001171 const std::string &file_name);
1172
1173// Generate Lua files from the definitions in the Parser object.
1174// See idl_gen_lua.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001175extern bool GenerateLua(const Parser &parser, const std::string &path,
1176 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001177
1178// Generate Rust files from the definitions in the Parser object.
1179// See idl_gen_rust.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001180extern bool GenerateRust(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001181 const std::string &file_name);
1182
1183// Generate Json schema file
1184// See idl_gen_json_schema.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001185extern bool GenerateJsonSchema(const Parser &parser, const std::string &path,
1186 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001187
1188extern bool GenerateKotlin(const Parser &parser, const std::string &path,
1189 const std::string &file_name);
1190
Austin Schuh272c6132020-11-14 16:37:52 -08001191// Generate Swift classes.
1192// See idl_gen_swift.cpp
1193extern bool GenerateSwift(const Parser &parser, const std::string &path,
1194 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001195
1196// Generate a schema file from the internal representation, useful after
1197// parsing a .proto schema.
1198extern std::string GenerateFBS(const Parser &parser,
1199 const std::string &file_name);
Austin Schuh272c6132020-11-14 16:37:52 -08001200extern bool GenerateFBS(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001201 const std::string &file_name);
1202
James Kuszmaul8e62b022022-03-22 09:33:25 -07001203// Generate a make rule for the generated TypeScript code.
1204// See idl_gen_ts.cpp.
1205extern std::string TSMakeRule(const Parser &parser, const std::string &path,
1206 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001207
1208// Generate a make rule for the generated C++ header.
1209// See idl_gen_cpp.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001210extern std::string CPPMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001211 const std::string &file_name);
1212
1213// Generate a make rule for the generated Dart code
1214// see idl_gen_dart.cpp
Austin Schuh272c6132020-11-14 16:37:52 -08001215extern std::string DartMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001216 const std::string &file_name);
1217
1218// Generate a make rule for the generated Rust code.
1219// See idl_gen_rust.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001220extern std::string RustMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001221 const std::string &file_name);
1222
Austin Schuh272c6132020-11-14 16:37:52 -08001223// Generate a make rule for generated Java or C# files.
1224// See code_generators.cpp.
James Kuszmaul8e62b022022-03-22 09:33:25 -07001225extern std::string CSharpMakeRule(const Parser &parser, const std::string &path,
1226 const std::string &file_name);
1227extern std::string JavaMakeRule(const Parser &parser, const std::string &path,
1228 const std::string &file_name);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001229
1230// Generate a make rule for the generated text (JSON) files.
1231// See idl_gen_text.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001232extern std::string TextMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001233 const std::string &file_names);
1234
1235// Generate a make rule for the generated binary files.
Austin Schuh272c6132020-11-14 16:37:52 -08001236// See code_generators.cpp.
1237extern std::string BinaryMakeRule(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001238 const std::string &file_name);
1239
1240// Generate GRPC Cpp interfaces.
1241// See idl_gen_grpc.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001242bool GenerateCppGRPC(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001243 const std::string &file_name);
1244
1245// Generate GRPC Go interfaces.
1246// See idl_gen_grpc.cpp.
Austin Schuh272c6132020-11-14 16:37:52 -08001247bool GenerateGoGRPC(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001248 const std::string &file_name);
1249
1250// Generate GRPC Java classes.
1251// See idl_gen_grpc.cpp
Austin Schuh272c6132020-11-14 16:37:52 -08001252bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001253 const std::string &file_name);
1254
Austin Schuh272c6132020-11-14 16:37:52 -08001255// Generate GRPC Python interfaces.
1256// See idl_gen_grpc.cpp.
1257bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
1258 const std::string &file_name);
1259
1260// Generate GRPC Swift interfaces.
1261// See idl_gen_grpc.cpp.
1262extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
1263 const std::string &file_name);
1264
1265extern bool GenerateTSGRPC(const Parser &parser, const std::string &path,
James Kuszmaul8e62b022022-03-22 09:33:25 -07001266 const std::string &file_name);
1267
1268extern bool GenerateRustModuleRootFile(const Parser &parser,
1269 const std::string &path);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001270} // namespace flatbuffers
1271
1272#endif // FLATBUFFERS_IDL_H_