// test schema file

include "attributes.fbs";
include "include_test1.fbs";

struct InGlobalNamespace { unused: byte; }

namespace MyGame;

table InParentNamespace {}

namespace MyGame.Example2;

table Monster {}  // Test having same name as below, but in different namespace.

table Strange {}

// Test schema reserved keywords as identifier
// Can be disabled in config/config.h
// It is still a good idea to use a namespace
// to avoid conflicts with host language names
// especially for enums and structs.
// Reserved names can be important in some JSON
// related use cases.
table S2 {
    namespace : int;
    table : int;
    struct : int;
    union : int;
    int : int;
}

// Enums fields can also be reserved, and these are also visible in
// JSON, but they cannot be used as table field defaults because
// type expressions do interpret keywords as keywords. For the same
// reason it is of no use to allow reserved names as type names
// such as table names.
enum foo:int { x, y, table }

namespace MyGame.Example;

// Note: parent namespace resolution only works without namespace prefix
//
// Won't work:
//    union Foo { Example2.InParentNamespace }
union Foo { InParentNamespace }


namespace MyGame.Example2.SubSystem;

// Note:
//
// parent namespace resolution only works without namespace prefix
// or with a global namespace prefix (a fully qualified name), not
// something in between.
// (There is no really good reason for this, it just isn't implemented,
//  and flatc JSON enum parsing works the same way.)
// The more local name wins any conflict.
//
union SubSystemA { Strange }
union SubSystemB { MyGame.Example2.Strange }

// Works in C++ flatc 1.8 but won't work with flatcc:
// union SubSystemC { Example2.Strange }


namespace MyGame.Example;

// test case for negative enum values
enum neg_enum:int {
  neg1 = -12,
  neg2 = -11,
  neg3 = -10,
}

enum int_enum:int {
    intneg = -02,
    intneg2 = -1,
    int1 = 02,
    int2 = 42,
}

// test for hex constants
enum hex_enum:int {
    hexneg = -0x02,
    hex1 = 0x3,
    hex2 = 0x7eafbeaf,
}

attribute "priority";

enum Color:byte (bit_flags) { Red = 0, Green, Blue = 3, }

// Note:
// For historic reasons C++ flatc 1.8 does permit conflicting base names
// from different namespaces without explicitly resolving the conflict.
//
// flatcc does not, and cannot, support this because it needs a unique
// base name to assign to the enumaration of union members - otherwise
// these enumerations could not have a namespace prefix - which is used
// in JSON and in default value assignment in the schema.
//
// Wont' work in flatc:
//    union Any { Monster, TestSimpleTableWithEnum, MyGame.Example2.Monster }

union Any {
    Monster,
    TestSimpleTableWithEnum,
    Monster2: MyGame.Example2.Monster,
    Alt
}

struct Test { a:short; b:byte; }

enum notemptyenum:int { x}

table TestSimpleTableWithEnum (csharp_partial) {
  color: Color = Green;
  color2: Color = Color.Green;
  uc : ubyte = MyGame.Example.Color.Green;
  uc2 : ubyte = Color.Green;

  // C++ flatc 1.8 dislikes enum values on non-enums
  // color2: Color = Green;
  // C++ flatc 1.8 dislikes enum values on non-enums
  // uc : ubyte = 1;
  // C++ flatc 1.8 dislikes enum values on non-enums, and namespace prefix
  // uc2 : ubyte = 1;
}

table TestInclude {
  global:InGlobalNamespace;
  incval:MyGame.OtherNameSpace.FromInclude;
  incval2:MyGame.OtherNameSpace.FromInclude = IncludeVal;
  incval3 : int (included_attribute);
  incval4:MyGame.OtherNameSpace.FromInclude = MyGame.OtherNameSpace.FromInclude.IncludeVal;
  incval5: long = MyGame.OtherNameSpace.FromInclude.IncludeVal;

  // C++ flatc 1.8 dislikes namespace prefix
  // incval4:MyGame.OtherNameSpace.FromInclude = IncludeVal;
  // C++ flatc 1.8 dislikes enum values on non-enums, and namespace prefix
  // incval5: long = 0;
}

struct Vec3 (force_align: 16) {
  x:float;
  y:float;
  z:float;
  test1:double;
  test2:Color;
  test3:Test;
}

struct Ability {
  id:uint(key);
  distance:uint;
}

table Stat {
  id:string;
  val:long;
  count:ushort;
}

// fixed length arrays new to flatcc 0.6.0
struct FooBar {
    foo:[float:0x10];
    bar:[int:10];
    col:[Color:3];
    tests:[Test:2];
    text:[char:5];
}

// `sorted` attribute new to flatcc 0.6.0, not supported by flatc 1.8.
// tables with direct or indirect vector content marked as sorted
// will get a mutable sort operation that recursively sorts all
// such vectors. 'sorted` is only valid for non-union vectors.
//
// attribute "sorted";
//
table Alt {
  prefix: TestJSONPrefix;
  movie:Fantasy.Movie;
  manyany: [Any];
  multik: [MultipleKeys] (sorted);
  rapunzels:[Fantasy.Rapunzel] (sorted);
  names:[string] (sorted);
  samples:[float32] (sorted);
  fixed_array: FooBar;
}

table TestJSONPrefix {
  testjsonprefixparsing:TestJSONPrefixParsing;
  testjsonprefixparsing2:TestJSONPrefixParsing2;
  testjsonprefixparsing3:TestJSONPrefixParsing3;
}

table TestJSONPrefixParsing
{
  aaaa: string;
  aaaa12345: uint;

  bbbb: string;
  bbbb1234: long;

  cccc: string;
  cccc1234: long;
  cccc12345: uint;

  dddd1234: long;
  dddd12345: uint;
}

// when there are two keys ending in same 8 character group
table TestJSONPrefixParsing2
{
    aaaa_bbbb_steps: long;
    aaaa_bbbb_start_: uint;
}

// when there are two keys ending in different 8 character group
table TestJSONPrefixParsing3
{
    aaaa_bbbb_steps: long;
    aaaa_bbbb_start_steps: uint;
}

// C++ flatc 1.8 does not yet support base64 as a built-in
// attribute "base64";
// attribute "base64url";

table TestBase64
{
    data:[ubyte] (base64);
    urldata:[ubyte] (base64url);
    nested:[ubyte] (nested_flatbuffer: "Monster", base64);
}

// 'primary_key' attribute new to flatcc 0.6.0, not supported by flatc 1.8.
// Allow multiple keys and allow one to be the default find and sort key
// even if not listed first. A table with a single key field behaves the
// same as a table with a single primary_key field, so use key for
// compatiblity in that case.
// 
// attribute "primary_key";
//
table MultipleKeys
{
    hello: string;
    world: string (key);
    foobar: int64 (primary_key);
}

table Monster {
  pos:Vec3 (id: 0);
  hp:short = 100 (id: 2);
  mana:short = 150 (id: 1);
  name:string (id: 3, required, key);
  color:Color = Blue (id: 6);
  inventory:[ubyte] (id: 5);
  friendly:bool = false (deprecated, priority: 1, id: 4);
  /// an example documentation comment: this will end up in the generated code
  /// multiline too
  testarrayoftables:[Monster] (id: 11);
  testarrayofstring:[string] (id: 10);
  testarrayofstring2:[string] (id: 28);
  testarrayofbools:[bool] (id: 24);
  testarrayofsortedstruct:[Ability] (id: 29);
  enemy:MyGame.Example.Monster (id:12);  // Test referring by full namespace.
  // id 7 resever for Any_type
  test:Any (id: 8);
  test4:[Test] (id: 9);
  test5:[Test] (id: 31);
  testnestedflatbuffer:[ubyte] (id:13, nested_flatbuffer: "Monster");
  testempty:Stat (id:14);
  testbool:bool = 1 (id:15);
  testhashs32_fnv1:int (id:16, hash:"fnv1_32");
  testhashu32_fnv1:uint (id:17, hash:"fnv1_32");
  testhashs64_fnv1:long (id:18, hash:"fnv1_64");
  testhashu64_fnv1:ulong (id:19, hash:"fnv1_64");
  testhashs32_fnv1a:int (id:20, hash:"fnv1a_32");
  testhashu32_fnv1a:uint (id:21, hash:"fnv1a_32", cpp_type:"Stat");
  testhashs64_fnv1a:long (id:22, hash:"fnv1a_64");
  testhashu64_fnv1a:ulong (id:23, hash:"fnv1a_64");

  // Googles flatc uses Pi as default be we don't because it
  // messes up JSON tests because the numeric print format is
  // configuration dependent.
  //testf:float = 3.14159 (id:25);
  testf:float = 3.14159e5 (id:25);
  testf2:float = 3 (id:26);
  testf3:float (id:27);
  flex:[ubyte] (id:30, flexbuffer);
  vector_of_longs:[long] (id:32);
  vector_of_doubles:[double] (id:33);
  parent_namespace_test:InParentNamespace (id:34);
  testbase64:TestBase64 (id:35);
}

table TypeAliases {
    i8:int8;
    u8:uint8;
    i16:int16;
    u16:uint16;
    i32:int32;
    u32:uint32;
    i64:int64;
    u64:uint64;
    f32:float32;
    f64:float64;
    v8:[int8];
    vf64:[float64];
}

rpc_service MonsterStorage {
  Store(Monster):Stat (streaming: "none");
  Retrieve(Stat):Monster (streaming: "server", idempotent);
}

// Demonstrates the ability to have vectors of unions, and also to
// store structs and strings in unions.

namespace Fantasy;

table Attacker {
    sword_attack_damage: int;
}

struct Rapunzel {
    hair_length: uint16 (key);
    travel_points: int (deprecated);
}

struct BookReader {
    books_read: int;
}

union Character {
    MuLan: Attacker = 2,  // Can have name be different from type.
    Rapunzel = 8,         // Or just both the same, as before.
    Belle: Fantasy.BookReader,
    BookFan: BookReader,
    Other: string,
    Unused: string = 255
}

table Movie {
    main_character: Character;
    antagonist: Character;
    side_kick: Character;
    cameo: Character;
    characters: [Character];
}

root_type MyGame.Example.Monster;

file_identifier "MONS";
file_extension "mon";

// Out of order enums

enum ReorderedEnum: int { rx = 10, ry = 1, rz = 9 }

enum ReorderedColor:byte (bit_flags) { RBlue = 3, RRed = 0, RGreen }

