forked from BigfootDev/flatbuffers
Adds implementation flag for swift (#7202)
* Adds implementation flag for swift Forces internal flag when using @_implementationOnly in swift Fixes access type for verifier functions & encoder functions Updates generated code * Addresses PR comments & adds a code gen dir within the swift tests * Adds test case for no-include * Fixes code gen script Removes prefix
This commit is contained in:
@@ -551,6 +551,7 @@ struct IDLOptions {
|
||||
bool output_enum_identifiers;
|
||||
bool prefixed_enums;
|
||||
bool scoped_enums;
|
||||
bool swift_implementation_only;
|
||||
bool include_dependence_headers;
|
||||
bool mutable_buffer;
|
||||
bool one_file;
|
||||
@@ -658,6 +659,7 @@ struct IDLOptions {
|
||||
output_enum_identifiers(true),
|
||||
prefixed_enums(true),
|
||||
scoped_enums(false),
|
||||
swift_implementation_only(false),
|
||||
include_dependence_headers(true),
|
||||
mutable_buffer(false),
|
||||
one_file(false),
|
||||
|
||||
@@ -63,6 +63,7 @@ assert flatc_path.exists(), "Cannot find the flatc compiler " + str(flatc_path)
|
||||
|
||||
# Specify the other paths that will be referenced
|
||||
tests_path = Path(root_path, "tests")
|
||||
swift_code_gen = Path(root_path, "tests/FlatBuffers.Test.Swift/CodeGenerationTests")
|
||||
samples_path = Path(root_path, "samples")
|
||||
reflection_path = Path(root_path, "reflection")
|
||||
|
||||
@@ -138,6 +139,12 @@ RUST_SERIALIZE_OPTS = BASE_OPTS + [
|
||||
TS_OPTS = ["--ts", "--gen-name-strings"]
|
||||
LOBSTER_OPTS = ["--lobster"]
|
||||
SWIFT_OPTS = ["--swift", "--gen-json-emit", "--bfbs-filenames", str(tests_path)]
|
||||
SWIFT_OPTS_CODE_GEN = [
|
||||
"--swift",
|
||||
"--gen-json-emit",
|
||||
"--bfbs-filenames",
|
||||
swift_code_gen
|
||||
]
|
||||
JAVA_OPTS = ["--java"]
|
||||
KOTLIN_OPTS = ["--kotlin"]
|
||||
PHP_OPTS = ["--php"]
|
||||
@@ -380,6 +387,18 @@ flatc(
|
||||
prefix=swift_prefix,
|
||||
)
|
||||
|
||||
flatc(
|
||||
SWIFT_OPTS_CODE_GEN + BASE_OPTS + ["--grpc", "--swift-implementation-only"],
|
||||
schema="test_import.fbs",
|
||||
cwd=swift_code_gen
|
||||
)
|
||||
|
||||
flatc(
|
||||
SWIFT_OPTS_CODE_GEN + NO_INCL_OPTS + ["--grpc"],
|
||||
schema="test_no_include.fbs",
|
||||
cwd=swift_code_gen
|
||||
)
|
||||
|
||||
# --filename-suffix and --filename-ext tests
|
||||
flatc(
|
||||
CPP_OPTS + NO_INCL_OPTS + ["--filename-suffix", "_suffix", "--filename-ext", "hpp"],
|
||||
|
||||
@@ -86,6 +86,8 @@ const static FlatCOption options[] = {
|
||||
{ "", "scoped-enums", "",
|
||||
"Use C++11 style scoped and strongly typed enums. Also implies "
|
||||
"--no-prefix." },
|
||||
{ "", "swift-implementation-only", "",
|
||||
"Adds a @_implementationOnly to swift imports" },
|
||||
{ "", "gen-inclues", "",
|
||||
"(deprecated), this is the default behavior. If the original behavior is "
|
||||
"required (no include statements) use --no-includes." },
|
||||
@@ -490,6 +492,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
|
||||
opts.java_checkerframework = true;
|
||||
} else if (arg == "--gen-generated") {
|
||||
opts.gen_generated = true;
|
||||
} else if (arg == "--swift-implementation-only") {
|
||||
opts.swift_implementation_only = true;
|
||||
} else if (arg == "--gen-json-emit") {
|
||||
opts.gen_json_coders = true;
|
||||
} else if (arg == "--object-prefix") {
|
||||
|
||||
@@ -167,8 +167,12 @@ class SwiftGenerator : public BaseGenerator {
|
||||
code_ += "// " + std::string(FlatBuffersGeneratedWarning());
|
||||
code_ += "// swiftlint:disable all";
|
||||
code_ += "// swiftformat:disable all\n";
|
||||
if (parser_.opts.include_dependence_headers || parser_.opts.generate_all)
|
||||
if (parser_.opts.include_dependence_headers || parser_.opts.generate_all) {
|
||||
if (parser_.opts.swift_implementation_only)
|
||||
code_ += "@_implementationOnly \\";
|
||||
|
||||
code_ += "import FlatBuffers\n";
|
||||
}
|
||||
|
||||
// Generate code for all the enum declarations.
|
||||
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
|
||||
@@ -212,6 +216,7 @@ class SwiftGenerator : public BaseGenerator {
|
||||
// Generates the reader for swift
|
||||
void GenStructReader(const StructDef &struct_def) {
|
||||
const bool is_private_access =
|
||||
parser_.opts.swift_implementation_only ||
|
||||
struct_def.attributes.Lookup("private") != nullptr;
|
||||
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
|
||||
GenComment(struct_def.doc_comment);
|
||||
@@ -286,7 +291,8 @@ class SwiftGenerator : public BaseGenerator {
|
||||
}
|
||||
code_ += "";
|
||||
code_ +=
|
||||
"public static func verify<T>(_ verifier: inout Verifier, at position: "
|
||||
"{{ACCESS_TYPE}} static func verify<T>(_ verifier: inout Verifier, at "
|
||||
"position: "
|
||||
"Int, of type: T.Type) throws where T: Verifiable {";
|
||||
Indent();
|
||||
code_ +=
|
||||
@@ -371,6 +377,7 @@ class SwiftGenerator : public BaseGenerator {
|
||||
// Generates the create function for swift
|
||||
void GenStructWriter(const StructDef &struct_def) {
|
||||
const bool is_private_access =
|
||||
parser_.opts.swift_implementation_only ||
|
||||
struct_def.attributes.Lookup("private") != nullptr;
|
||||
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
|
||||
code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
|
||||
@@ -440,6 +447,7 @@ class SwiftGenerator : public BaseGenerator {
|
||||
// Generates the reader for swift
|
||||
void GenTable(const StructDef &struct_def) {
|
||||
const bool is_private_access =
|
||||
parser_.opts.swift_implementation_only ||
|
||||
struct_def.attributes.Lookup("private") != nullptr;
|
||||
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
|
||||
GenObjectHeader(struct_def);
|
||||
@@ -699,7 +707,7 @@ class SwiftGenerator : public BaseGenerator {
|
||||
field.value.type.struct_def->fixed) &&
|
||||
(IsVector(field.value.type) || IsArray(field.value.type))) {
|
||||
const auto field_name = namer_.NamespacedType(*vectortype.struct_def);
|
||||
code_ += "public static func " +
|
||||
code_ += "{{ACCESS_TYPE}} static func " +
|
||||
namer_.Method("start_vector_of", field_var) +
|
||||
"(_ size: Int, in builder: inout "
|
||||
"FlatBufferBuilder) {";
|
||||
@@ -1054,7 +1062,7 @@ class SwiftGenerator : public BaseGenerator {
|
||||
code_ += "";
|
||||
if (struct_def.fields.vec.empty() == false) GenerateCodingKeys(struct_def);
|
||||
|
||||
code_ += "public func encode(to encoder: Encoder) throws {";
|
||||
code_ += "{{ACCESS_TYPE}} func encode(to encoder: Encoder) throws {";
|
||||
Indent();
|
||||
if (struct_def.fields.vec.empty() == false) GenerateEncoderBody(struct_def);
|
||||
Outdent();
|
||||
@@ -1066,7 +1074,8 @@ class SwiftGenerator : public BaseGenerator {
|
||||
|
||||
void GenerateVerifier(const StructDef &struct_def) {
|
||||
code_ +=
|
||||
"public static func verify<T>(_ verifier: inout Verifier, at position: "
|
||||
"{{ACCESS_TYPE}} static func verify<T>(_ verifier: inout Verifier, at "
|
||||
"position: "
|
||||
"Int, of type: T.Type) throws where T: Verifiable {";
|
||||
Indent();
|
||||
code_ += "var _v = try verifier.visitTable(at: position)";
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
table Message {
|
||||
internal_message: string;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// swiftlint:disable all
|
||||
// swiftformat:disable all
|
||||
|
||||
@_implementationOnly import FlatBuffers
|
||||
|
||||
internal struct Message: FlatBufferObject, Verifiable, ObjectAPIPacker {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_2_0_0() }
|
||||
internal var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Table
|
||||
|
||||
internal static func getRootAsMessage(bb: ByteBuffer) -> Message { return Message(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
|
||||
|
||||
private init(_ t: Table) { _accessor = t }
|
||||
internal init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
|
||||
|
||||
private enum VTOFFSET: VOffset {
|
||||
case internalMessage = 4
|
||||
var v: Int32 { Int32(self.rawValue) }
|
||||
var p: VOffset { self.rawValue }
|
||||
}
|
||||
|
||||
internal var internalMessage: String? { let o = _accessor.offset(VTOFFSET.internalMessage.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
internal var internalMessageSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.internalMessage.v) }
|
||||
internal static func startMessage(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) }
|
||||
internal static func add(internalMessage: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: internalMessage, at: VTOFFSET.internalMessage.p) }
|
||||
internal static func endMessage(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
|
||||
internal static func createMessage(
|
||||
_ fbb: inout FlatBufferBuilder,
|
||||
internalMessageOffset internalMessage: Offset = Offset()
|
||||
) -> Offset {
|
||||
let __start = Message.startMessage(&fbb)
|
||||
Message.add(internalMessage: internalMessage, &fbb)
|
||||
return Message.endMessage(&fbb, start: __start)
|
||||
}
|
||||
|
||||
|
||||
internal mutating func unpack() -> MessageT {
|
||||
return MessageT(&self)
|
||||
}
|
||||
internal static func pack(_ builder: inout FlatBufferBuilder, obj: inout MessageT?) -> Offset {
|
||||
guard var obj = obj else { return Offset() }
|
||||
return pack(&builder, obj: &obj)
|
||||
}
|
||||
|
||||
internal static func pack(_ builder: inout FlatBufferBuilder, obj: inout MessageT) -> Offset {
|
||||
let __internalMessage: Offset
|
||||
if let s = obj.internalMessage {
|
||||
__internalMessage = builder.create(string: s)
|
||||
} else {
|
||||
__internalMessage = Offset()
|
||||
}
|
||||
|
||||
let __root = Message.startMessage(&builder)
|
||||
Message.add(internalMessage: __internalMessage, &builder)
|
||||
return Message.endMessage(&builder, start: __root)
|
||||
}
|
||||
|
||||
internal static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
|
||||
var _v = try verifier.visitTable(at: position)
|
||||
try _v.visit(field: VTOFFSET.internalMessage.p, fieldName: "internalMessage", required: false, type: ForwardOffset<String>.self)
|
||||
_v.finish()
|
||||
}
|
||||
}
|
||||
|
||||
extension Message: Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case internalMessage = "internal_message"
|
||||
}
|
||||
internal func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(internalMessage, forKey: .internalMessage)
|
||||
}
|
||||
}
|
||||
|
||||
internal class MessageT: NativeObject {
|
||||
|
||||
internal var internalMessage: String?
|
||||
|
||||
internal init(_ _t: inout Message) {
|
||||
internalMessage = _t.internalMessage
|
||||
}
|
||||
|
||||
internal init() {
|
||||
}
|
||||
|
||||
internal func serialize() -> ByteBuffer { return serialize(type: Message.self) }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
table Message {
|
||||
internal_message: string;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// swiftlint:disable all
|
||||
// swiftformat:disable all
|
||||
|
||||
public struct Message: FlatBufferObject, Verifiable, ObjectAPIPacker {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_2_0_0() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Table
|
||||
|
||||
public static func getRootAsMessage(bb: ByteBuffer) -> Message { return Message(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
|
||||
|
||||
private init(_ t: Table) { _accessor = t }
|
||||
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
|
||||
|
||||
private enum VTOFFSET: VOffset {
|
||||
case internalMessage = 4
|
||||
var v: Int32 { Int32(self.rawValue) }
|
||||
var p: VOffset { self.rawValue }
|
||||
}
|
||||
|
||||
public var internalMessage: String? { let o = _accessor.offset(VTOFFSET.internalMessage.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var internalMessageSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.internalMessage.v) }
|
||||
public static func startMessage(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) }
|
||||
public static func add(internalMessage: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: internalMessage, at: VTOFFSET.internalMessage.p) }
|
||||
public static func endMessage(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
|
||||
public static func createMessage(
|
||||
_ fbb: inout FlatBufferBuilder,
|
||||
internalMessageOffset internalMessage: Offset = Offset()
|
||||
) -> Offset {
|
||||
let __start = Message.startMessage(&fbb)
|
||||
Message.add(internalMessage: internalMessage, &fbb)
|
||||
return Message.endMessage(&fbb, start: __start)
|
||||
}
|
||||
|
||||
|
||||
public mutating func unpack() -> MessageT {
|
||||
return MessageT(&self)
|
||||
}
|
||||
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MessageT?) -> Offset {
|
||||
guard var obj = obj else { return Offset() }
|
||||
return pack(&builder, obj: &obj)
|
||||
}
|
||||
|
||||
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MessageT) -> Offset {
|
||||
let __internalMessage: Offset
|
||||
if let s = obj.internalMessage {
|
||||
__internalMessage = builder.create(string: s)
|
||||
} else {
|
||||
__internalMessage = Offset()
|
||||
}
|
||||
|
||||
let __root = Message.startMessage(&builder)
|
||||
Message.add(internalMessage: __internalMessage, &builder)
|
||||
return Message.endMessage(&builder, start: __root)
|
||||
}
|
||||
|
||||
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
|
||||
var _v = try verifier.visitTable(at: position)
|
||||
try _v.visit(field: VTOFFSET.internalMessage.p, fieldName: "internalMessage", required: false, type: ForwardOffset<String>.self)
|
||||
_v.finish()
|
||||
}
|
||||
}
|
||||
|
||||
extension Message: Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case internalMessage = "internal_message"
|
||||
}
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(internalMessage, forKey: .internalMessage)
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageT: NativeObject {
|
||||
|
||||
public var internalMessage: String?
|
||||
|
||||
public init(_ _t: inout Message) {
|
||||
internalMessage = _t.internalMessage
|
||||
}
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func serialize() -> ByteBuffer { return serialize(type: Message.self) }
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
swift_dir=`pwd`
|
||||
cd ..
|
||||
test_dir=`pwd`
|
||||
alias fbc='${test_dir}/../flatc'
|
||||
alias fbc='${test_dir}/../Debug/flatc'
|
||||
shopt -s expand_aliases
|
||||
|
||||
cd ${swift_dir}/Tests/FlatBuffers.Test.SwiftTests
|
||||
@@ -11,6 +11,12 @@ fbc --swift --gen-json-emit --gen-object-api ${test_dir}/more_defaults.fbs
|
||||
fbc --swift --gen-json-emit --gen-mutable --gen-object-api ${test_dir}/MutatingBool.fbs
|
||||
cd ${swift_dir}
|
||||
|
||||
# Goes into the code generation tests
|
||||
cd CodeGenerationTests
|
||||
fbc --swift --gen-mutable --grpc --gen-json-emit --gen-object-api --swift-implementation-only test_import.fbs
|
||||
fbc --swift --gen-mutable --grpc --gen-json-emit --gen-object-api --no-includes test_no_include.fbs
|
||||
cd ..
|
||||
|
||||
cd ${swift_dir}/Sources/SwiftFlatBuffers
|
||||
# create better fuzzing test file
|
||||
fbc --swift --gen-json-emit fuzzer.fbs
|
||||
|
||||
@@ -830,7 +830,7 @@ internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferObject, Verifi
|
||||
return MyGame_Example_TestSimpleTableWithEnum.endTestSimpleTableWithEnum(&builder, start: __root)
|
||||
}
|
||||
|
||||
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
|
||||
internal static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
|
||||
var _v = try verifier.visitTable(at: position)
|
||||
try _v.visit(field: VTOFFSET.color.p, fieldName: "color", required: false, type: MyGame_Example_Color.self)
|
||||
_v.finish()
|
||||
@@ -842,7 +842,7 @@ extension MyGame_Example_TestSimpleTableWithEnum: Encodable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case color = "color"
|
||||
}
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
internal func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if color != .green {
|
||||
try container.encodeIfPresent(color, forKey: .color)
|
||||
|
||||
Reference in New Issue
Block a user