Commit f11ffedb authored by Kamil Rojewski's avatar Kamil Rojewski Committed by Wouter van Oortmerssen

Vector of unions support for java and c# (#4735)

* Eclipse ignore

* TypeScript support

* Prefixing enums

* Test results

* Merged JS and TS generators

* Fixed AppVeyor build problems

* Fixed more AppVeyor build problems

* Fixed more AppVeyor build problems

* Changed TS flag to options struct

* Storing options by value

* Removed unneeded const

* Re-export support for unions

* Uint support

* Casting bools to numbers for mutation

* TS shell tests

* Reverted generates js test file to original version

* Backing up js tests and properly generating test data

* Not importing flatbuffers for TS test generation

* Not overwriting generated js for tests

* AppVeyor test fixes

* Generating the most strict TS code possible

* Not returning null when creating vectors

* Not returning null from struct contructors

* Vector of unions for ts/js

* Sanity check for languages

* Indentation fix + output test files

* Vectors of unions for php

* Fixes to union vector handling + tests

* Fix for strictPropertyInitialization

* Fix for new aligned operator new for gcc >= 7.1

* Not generating imports/ns prefixes with --gen-all

* TypeScript docs

* Missing imports of enums

* Missing TS links

* Enabled vector of unions for java, since it seems to work

* Added jitpack config

* Added obj to vector of unions getter

* Removed unneeded accessor

* Bumped jdk version in pom.xml

* Vector of unions support for c#
parent 5d42c835
......@@ -47,8 +47,8 @@
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>1.8</source>
<target>1.8</target>
</configuration>
<version>3.2</version>
</plugin>
......
......@@ -853,7 +853,8 @@ class GeneralGenerator : public BaseGenerator {
(field.value.type.base_type == BASE_TYPE_STRUCT ||
field.value.type.base_type == BASE_TYPE_UNION ||
(field.value.type.base_type == BASE_TYPE_VECTOR &&
field.value.type.element == BASE_TYPE_STRUCT))) {
(field.value.type.element == BASE_TYPE_STRUCT ||
field.value.type.element == BASE_TYPE_UNION)))) {
optional = lang_.optional_suffix;
conditional_cast = "(" + type_name_dest + optional + ")";
}
......@@ -891,7 +892,9 @@ class GeneralGenerator : public BaseGenerator {
code += MakeCamel(field.name, lang_.first_camel_upper);
code += "(new " + type_name + "(), j); }\n";
}
} else if (field.value.type.base_type == BASE_TYPE_UNION) {
} else if (field.value.type.base_type == BASE_TYPE_UNION ||
(field.value.type.base_type == BASE_TYPE_VECTOR &&
field.value.type.VectorType().base_type == BASE_TYPE_UNION)) {
if (lang_.language == IDLOptions::kCSharp) {
// Union types in C# use generic Table-derived type for better type
// safety.
......@@ -963,13 +966,30 @@ class GeneralGenerator : public BaseGenerator {
break;
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_UNION &&
lang_.language == IDLOptions::kCSharp) {
conditional_cast = "(TTable?)";
getter += "<TTable>";
}
code += "(";
if (vectortype.base_type == BASE_TYPE_STRUCT) {
if (lang_.language != IDLOptions::kCSharp)
code += type_name + " obj, ";
getter = obj + ".__assign";
} else if (vectortype.base_type == BASE_TYPE_UNION) {
if (lang_.language != IDLOptions::kCSharp)
code += type_name + " obj, ";
}
code += "int j)";
const auto body = offset_prefix + conditional_cast + getter + "(";
if (vectortype.base_type == BASE_TYPE_UNION) {
if (lang_.language != IDLOptions::kCSharp)
code += body + "obj, ";
else
code += " where TTable : struct, IFlatbufferObject" + body;
} else {
code += body;
}
code += "int j)" + offset_prefix + conditional_cast + getter + "(";
auto index = lang_.accessor_prefix + "__vector(o) + j * " +
NumToString(InlineSize(vectortype));
if (vectortype.base_type == BASE_TYPE_STRUCT) {
......
......@@ -1623,7 +1623,8 @@ CheckedError Parser::CheckClash(std::vector<FieldDef *> &fields,
bool Parser::SupportsVectorOfUnions() const {
return opts.lang_to_generate != 0 &&
(opts.lang_to_generate & ~(IDLOptions::kCpp | IDLOptions::kJs |
IDLOptions::kTs | IDLOptions::kPhp)) == 0;
IDLOptions::kTs | IDLOptions::kPhp |
IDLOptions::kJava | IDLOptions::kCSharp)) == 0;
}
Namespace *Parser::UniqueNamespace(Namespace *ns) {
......
......@@ -3,7 +3,7 @@
# Testing C# on Linux using Mono.
mcs -debug -out:./fbnettest.exe \
../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/*.cs \
../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/*.cs ../union_vector/*.cs \
FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
mono --debug ./fbnettest.exe
rm fbnettest.exe
......@@ -14,7 +14,7 @@ rm Resources/monsterdata_cstest_sp.mon
mcs -debug -out:./fbnettest.exe \
-unsafe -d:UNSAFE_BYTEBUFFER \
../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/*.cs \
../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/*.cs ../union_vector/*.cs\
FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
mono --debug ./fbnettest.exe
rm fbnettest.exe
......
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
using global::System;
using global::FlatBuffers;
public struct Attacker : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static Attacker GetRootAsAttacker(ByteBuffer _bb) { return GetRootAsAttacker(_bb, new Attacker()); }
public static Attacker GetRootAsAttacker(ByteBuffer _bb, Attacker obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public Attacker __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public int SwordAttackDamage { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
public static Offset<Attacker> CreateAttacker(FlatBufferBuilder builder,
int sword_attack_damage = 0) {
builder.StartObject(1);
Attacker.AddSwordAttackDamage(builder, sword_attack_damage);
return Attacker.EndAttacker(builder);
}
public static void StartAttacker(FlatBufferBuilder builder) { builder.StartObject(1); }
public static void AddSwordAttackDamage(FlatBufferBuilder builder, int swordAttackDamage) { builder.AddInt(0, swordAttackDamage, 0); }
public static Offset<Attacker> EndAttacker(FlatBufferBuilder builder) {
int o = builder.EndObject();
return new Offset<Attacker>(o);
}
};
// automatically generated by the FlatBuffers compiler, do not modify
import java.nio.*;
import java.lang.*;
import java.util.*;
import com.google.flatbuffers.*;
@SuppressWarnings("unused")
public final class Attacker extends Table {
public static Attacker getRootAsAttacker(ByteBuffer _bb) { return getRootAsAttacker(_bb, new Attacker()); }
public static Attacker getRootAsAttacker(ByteBuffer _bb, Attacker obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public Attacker __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public int swordAttackDamage() { int o = __offset(4); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
public static int createAttacker(FlatBufferBuilder builder,
int sword_attack_damage) {
builder.startObject(1);
Attacker.addSwordAttackDamage(builder, sword_attack_damage);
return Attacker.endAttacker(builder);
}
public static void startAttacker(FlatBufferBuilder builder) { builder.startObject(1); }
public static void addSwordAttackDamage(FlatBufferBuilder builder, int swordAttackDamage) { builder.addInt(0, swordAttackDamage, 0); }
public static int endAttacker(FlatBufferBuilder builder) {
int o = builder.endObject();
return o;
}
}
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
using global::System;
using global::FlatBuffers;
public struct BookReader : IFlatbufferObject
{
private Struct __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public BookReader __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public int BooksRead { get { return __p.bb.GetInt(__p.bb_pos + 0); } }
public static Offset<BookReader> CreateBookReader(FlatBufferBuilder builder, int BooksRead) {
builder.Prep(4, 4);
builder.PutInt(BooksRead);
return new Offset<BookReader>(builder.Offset);
}
};
// automatically generated by the FlatBuffers compiler, do not modify
import java.nio.*;
import java.lang.*;
import java.util.*;
import com.google.flatbuffers.*;
@SuppressWarnings("unused")
public final class BookReader extends Struct {
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public BookReader __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public int booksRead() { return bb.getInt(bb_pos + 0); }
public static int createBookReader(FlatBufferBuilder builder, int booksRead) {
builder.prep(4, 4);
builder.putInt(booksRead);
return builder.offset();
}
}
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
public enum Character : byte
{
NONE = 0,
MuLan = 1,
Rapunzel = 2,
Belle = 3,
BookFan = 4,
Other = 5,
Unused = 6,
};
// automatically generated by the FlatBuffers compiler, do not modify
public final class Character {
private Character() { }
public static final byte NONE = 0;
public static final byte MuLan = 1;
public static final byte Rapunzel = 2;
public static final byte Belle = 3;
public static final byte BookFan = 4;
public static final byte Other = 5;
public static final byte Unused = 6;
public static final String[] names = { "NONE", "MuLan", "Rapunzel", "Belle", "BookFan", "Other", "Unused", };
public static String name(int e) { return names[e]; }
}
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
using global::System;
using global::FlatBuffers;
public struct Movie : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static Movie GetRootAsMovie(ByteBuffer _bb) { return GetRootAsMovie(_bb, new Movie()); }
public static Movie GetRootAsMovie(ByteBuffer _bb, Movie obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public static bool MovieBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "MOVI"); }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public Movie __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public Character MainCharacterType { get { int o = __p.__offset(4); return o != 0 ? (Character)__p.bb.Get(o + __p.bb_pos) : Character.NONE; } }
public TTable? MainCharacter<TTable>() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union<TTable>(o) : null; }
public Character CharactersType(int j) { int o = __p.__offset(8); return o != 0 ? (Character)__p.bb.Get(__p.__vector(o) + j * 1) : (Character)0; }
public int CharactersTypeLength { get { int o = __p.__offset(8); return o != 0 ? __p.__vector_len(o) : 0; } }
public ArraySegment<byte>? GetCharactersTypeBytes() { return __p.__vector_as_arraysegment(8); }
public TTable? Characters<TTable>(int j) where TTable : struct, IFlatbufferObject { int o = __p.__offset(10); return o != 0 ? (TTable?)__p.__union<TTable>(__p.__vector(o) + j * 4) : null; }
public int CharactersLength { get { int o = __p.__offset(10); return o != 0 ? __p.__vector_len(o) : 0; } }
public static Offset<Movie> CreateMovie(FlatBufferBuilder builder,
Character main_character_type = Character.NONE,
int main_characterOffset = 0,
VectorOffset characters_typeOffset = default(VectorOffset),
VectorOffset charactersOffset = default(VectorOffset)) {
builder.StartObject(4);
Movie.AddCharacters(builder, charactersOffset);
Movie.AddCharactersType(builder, characters_typeOffset);
Movie.AddMainCharacter(builder, main_characterOffset);
Movie.AddMainCharacterType(builder, main_character_type);
return Movie.EndMovie(builder);
}
public static void StartMovie(FlatBufferBuilder builder) { builder.StartObject(4); }
public static void AddMainCharacterType(FlatBufferBuilder builder, Character mainCharacterType) { builder.AddByte(0, (byte)mainCharacterType, 0); }
public static void AddMainCharacter(FlatBufferBuilder builder, int mainCharacterOffset) { builder.AddOffset(1, mainCharacterOffset, 0); }
public static void AddCharactersType(FlatBufferBuilder builder, VectorOffset charactersTypeOffset) { builder.AddOffset(2, charactersTypeOffset.Value, 0); }
public static VectorOffset CreateCharactersTypeVector(FlatBufferBuilder builder, Character[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte((byte)data[i]); return builder.EndVector(); }
public static void StartCharactersTypeVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); }
public static void AddCharacters(FlatBufferBuilder builder, VectorOffset charactersOffset) { builder.AddOffset(3, charactersOffset.Value, 0); }
public static VectorOffset CreateCharactersVector(FlatBufferBuilder builder, int[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i]); return builder.EndVector(); }
public static void StartCharactersVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static Offset<Movie> EndMovie(FlatBufferBuilder builder) {
int o = builder.EndObject();
return new Offset<Movie>(o);
}
public static void FinishMovieBuffer(FlatBufferBuilder builder, Offset<Movie> offset) { builder.Finish(offset.Value, "MOVI"); }
public static void FinishSizePrefixedMovieBuffer(FlatBufferBuilder builder, Offset<Movie> offset) { builder.FinishSizePrefixed(offset.Value, "MOVI"); }
};
// automatically generated by the FlatBuffers compiler, do not modify
import java.nio.*;
import java.lang.*;
import java.util.*;
import com.google.flatbuffers.*;
@SuppressWarnings("unused")
public final class Movie extends Table {
public static Movie getRootAsMovie(ByteBuffer _bb) { return getRootAsMovie(_bb, new Movie()); }
public static Movie getRootAsMovie(ByteBuffer _bb, Movie obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public static boolean MovieBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MOVI"); }
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public Movie __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public byte mainCharacterType() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; }
public Table mainCharacter(Table obj) { int o = __offset(6); return o != 0 ? __union(obj, o) : null; }
public byte charactersType(int j) { int o = __offset(8); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; }
public int charactersTypeLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; }
public ByteBuffer charactersTypeAsByteBuffer() { return __vector_as_bytebuffer(8, 1); }
public ByteBuffer charactersTypeInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 1); }
public Table characters(Table obj, int j) { int o = __offset(10); return o != 0 ? __union(obj, __vector(o) + j * 4) : null; }
public int charactersLength() { int o = __offset(10); return o != 0 ? __vector_len(o) : 0; }
public static int createMovie(FlatBufferBuilder builder,
byte main_character_type,
int main_characterOffset,
int characters_typeOffset,
int charactersOffset) {
builder.startObject(4);
Movie.addCharacters(builder, charactersOffset);
Movie.addCharactersType(builder, characters_typeOffset);
Movie.addMainCharacter(builder, main_characterOffset);
Movie.addMainCharacterType(builder, main_character_type);
return Movie.endMovie(builder);
}
public static void startMovie(FlatBufferBuilder builder) { builder.startObject(4); }
public static void addMainCharacterType(FlatBufferBuilder builder, byte mainCharacterType) { builder.addByte(0, mainCharacterType, 0); }
public static void addMainCharacter(FlatBufferBuilder builder, int mainCharacterOffset) { builder.addOffset(1, mainCharacterOffset, 0); }
public static void addCharactersType(FlatBufferBuilder builder, int charactersTypeOffset) { builder.addOffset(2, charactersTypeOffset, 0); }
public static int createCharactersTypeVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); }
public static void startCharactersTypeVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); }
public static void addCharacters(FlatBufferBuilder builder, int charactersOffset) { builder.addOffset(3, charactersOffset, 0); }
public static int createCharactersVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); }
public static void startCharactersVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); }
public static int endMovie(FlatBufferBuilder builder) {
int o = builder.endObject();
return o;
}
public static void finishMovieBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MOVI"); }
public static void finishSizePrefixedMovieBuffer(FlatBufferBuilder builder, int offset) { builder.finishSizePrefixed(offset, "MOVI"); }
}
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
using global::System;
using global::FlatBuffers;
public struct Rapunzel : IFlatbufferObject
{
private Struct __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public Rapunzel __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public int HairLength { get { return __p.bb.GetInt(__p.bb_pos + 0); } }
public static Offset<Rapunzel> CreateRapunzel(FlatBufferBuilder builder, int HairLength) {
builder.Prep(4, 4);
builder.PutInt(HairLength);
return new Offset<Rapunzel>(builder.Offset);
}
};
// automatically generated by the FlatBuffers compiler, do not modify
import java.nio.*;
import java.lang.*;
import java.util.*;
import com.google.flatbuffers.*;
@SuppressWarnings("unused")
public final class Rapunzel extends Struct {
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public Rapunzel __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public int hairLength() { return bb.getInt(bb_pos + 0); }
public static int createRapunzel(FlatBufferBuilder builder, int hairLength) {
builder.prep(4, 4);
builder.putInt(hairLength);
return builder.offset();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment