[Swift] adds support for default vectors and strings (#6461)

Small fix

Adhere to the new protocol names
This commit is contained in:
mustiikhalil
2021-02-19 12:47:28 +03:00
committed by GitHub
parent 7f47718b6d
commit ae603b9770
9 changed files with 254 additions and 37 deletions

View File

@@ -537,7 +537,8 @@ class SwiftGenerator : public BaseGenerator {
auto &create_func_header = *create_header;
auto name = Name(field);
auto type = GenType(field.value.type);
auto opt_scalar = field.IsOptional() && IsScalar(field.value.type.base_type);
auto opt_scalar =
field.IsOptional() && IsScalar(field.value.type.base_type);
auto nullable_type = opt_scalar ? type + "?" : type;
code_.SetValue("VALUENAME", name);
code_.SetValue("VALUETYPE", nullable_type);
@@ -560,7 +561,7 @@ class SwiftGenerator : public BaseGenerator {
"{{VALUETYPE}}" + builder_string + "fbb.add(element: {{VALUENAME}}\\";
code_ += field.IsOptional() ? (optional_enum + "\\")
: (is_enum + ", def: {{CONSTANT}}\\");
: (is_enum + ", def: {{CONSTANT}}\\");
code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
@@ -568,8 +569,9 @@ class SwiftGenerator : public BaseGenerator {
IsEnum(field.value.type)
? (field.IsOptional() ? "nil" : GenEnumDefaultValue(field))
: field.value.constant;
create_func_header.push_back("" + name + ": " + nullable_type + " = " +
(field.IsOptional() ? "nil" : default_value));
create_func_header.push_back(
"" + name + ": " + nullable_type + " = " +
(field.IsOptional() ? "nil" : default_value));
return;
}
@@ -583,8 +585,9 @@ class SwiftGenerator : public BaseGenerator {
"fbb.add(element: {{VALUENAME}},\\";
code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},";
code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
create_func_header.push_back(name + ": " + nullable_type + " = " +
(field.IsOptional() ? "nil" : default_value));
create_func_header.push_back(
name + ": " + nullable_type + " = " +
(field.IsOptional() ? "nil" : default_value));
return;
}
@@ -648,9 +651,8 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("VALUETYPE", type);
code_.SetValue("OFFSET", name);
code_.SetValue("CONSTANT", field.value.constant);
bool opt_scalar = field.IsOptional() && IsScalar(field.value.type.base_type);
std::string def_Val = opt_scalar ? "nil" : "{{CONSTANT}}";
std::string optional = opt_scalar ? "?" : "";
std::string def_Val = field.IsDefault() ? "{{CONSTANT}}" : "nil";
std::string optional = field.IsOptional() ? "?" : "";
auto const_string = "return o == 0 ? " + def_Val + " : ";
GenComment(field.doc_comment);
if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) &&
@@ -675,7 +677,8 @@ class SwiftGenerator : public BaseGenerator {
}
if (IsEnum(field.value.type)) {
auto default_value = field.IsOptional() ? "nil" : GenEnumDefaultValue(field);
auto default_value =
field.IsOptional() ? "nil" : GenEnumDefaultValue(field);
code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
code_ += GenReaderMainBody(optional) + "\\";
code_ += GenOffset() + "return o == 0 ? " + default_value + " : " +
@@ -709,9 +712,10 @@ class SwiftGenerator : public BaseGenerator {
GenConstructor(GenIndirect("o + {{ACCESS}}.postion"));
break;
case BASE_TYPE_STRING:
case BASE_TYPE_STRING: {
auto default_string = "\"" + field.value.constant + "\"";
code_.SetValue("VALUETYPE", GenType(field.value.type));
code_.SetValue("CONSTANT", "nil");
code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil");
code_ += GenReaderMainBody(is_required) + GenOffset() +
required_reader + "{{ACCESS}}.string(at: o) }";
code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}SegmentArray: [UInt8]" +
@@ -719,11 +723,9 @@ class SwiftGenerator : public BaseGenerator {
" { return "
"{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) }";
break;
}
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_VECTOR:
GenTableReaderVectorFields(field, const_string);
break;
case BASE_TYPE_VECTOR: GenTableReaderVectorFields(field); break;
case BASE_TYPE_UNION:
code_.SetValue("CONSTANT", "nil");
code_ +=
@@ -736,15 +738,14 @@ class SwiftGenerator : public BaseGenerator {
}
}
void GenTableReaderVectorFields(const FieldDef &field,
const std::string &const_string) {
void GenTableReaderVectorFields(const FieldDef &field) {
std::string const_string = "return o == 0 ? {{CONSTANT}} : ";
auto vectortype = field.value.type.VectorType();
code_.SetValue("SIZE", NumToString(InlineSize(vectortype)));
code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}Count: Int32 { " + GenOffset() +
const_string + "{{ACCESS}}.vector(count: o) }";
code_.SetValue("CONSTANT", IsScalar(vectortype.base_type) == true
? field.value.constant
: "nil");
"return o == 0 ? 0 : {{ACCESS}}.vector(count: o) }";
code_.SetValue("CONSTANT",
IsScalar(vectortype.base_type) == true ? "0" : "nil");
auto nullable = IsScalar(vectortype.base_type) == true ? "" : "?";
nullable = IsEnum(vectortype) == true ? "?" : nullable;
@@ -759,11 +760,10 @@ class SwiftGenerator : public BaseGenerator {
if (IsBool(vectortype.base_type)) {
code_.SetValue("CONSTANT", field.value.offset == 0 ? "false" : "true");
code_.SetValue("VALUETYPE", "Byte");
code_.SetValue("VALUETYPE", "Bool");
}
if (!IsEnum(vectortype))
code_ +=
const_string + (IsBool(vectortype.base_type) ? "0 != " : "") + "\\";
if (!IsEnum(vectortype)) code_ += const_string + "\\";
if (IsScalar(vectortype.base_type) && !IsEnum(vectortype) &&
!IsBool(field.value.type.base_type)) {
@@ -1166,9 +1166,9 @@ class SwiftGenerator : public BaseGenerator {
buffer_constructor.push_back("" + name + " = _t." + name);
} else {
buffer_constructor.push_back("var __" + name + " = _t." + name);
buffer_constructor.push_back("" + name + " = __" + name +
(field.IsRequired() ? "!" : question_mark) +
".unpack()");
buffer_constructor.push_back(
"" + name + " = __" + name +
(field.IsRequired() ? "!" : question_mark) + ".unpack()");
}
break;
}
@@ -1181,7 +1181,17 @@ class SwiftGenerator : public BaseGenerator {
case BASE_TYPE_STRING: {
code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: String" + is_required;
buffer_constructor.push_back(name + " = _t." + name);
if (field.IsRequired()) base_constructor.push_back(name + " = \"\"");
if (field.IsRequired()) {
std::string default_value =
field.IsDefault() ? field.value.constant : "";
base_constructor.push_back(name + " = \"" + default_value + "\"");
break;
}
if (field.IsDefault() && !field.IsRequired()) {
std::string value = field.IsDefault() ? field.value.constant : "nil";
base_constructor.push_back(name + " = \"" + value + "\"");
}
break;
}
case BASE_TYPE_UTYPE: break;

View File

@@ -2434,7 +2434,7 @@ bool Parser::SupportsOptionalScalars() const {
bool Parser::SupportsDefaultVectorsAndStrings() const {
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
IDLOptions::kRust;
IDLOptions::kRust | IDLOptions::kSwift;
return !(opts.lang_to_generate & ~supported_langs);
}

View File

@@ -10,6 +10,7 @@ cd ${test_dir}
cd ${swift_dir}/Tests/FlatBuffers.Test.SwiftTests
fbc --swift --gen-mutable --grpc --gen-object-api -I ${test_dir}/include_test ${test_dir}/monster_test.fbs ${test_dir}/union_vector/union_vector.fbs
fbc --swift ${test_dir}/optional_scalars.fbs
fbc --swift --gen-object-api ${test_dir}/more_defaults.fbs
cd ${swift_dir}
swift build --build-tests
swift test

View File

@@ -99,6 +99,24 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
readObjectApi(monster: unpacked)
}
func testArrayOfBools() {
let boolArray = [false, true, false, true, false, true, false]
var fbb = FlatBufferBuilder(initialSize: 1)
let name = fbb.create(string: "Frodo")
let bools = fbb.createVector(boolArray)
let root = Monster.createMonster(&fbb, offsetOfName: name, vectorOfTestarrayofbools: bools)
fbb.finish(offset: root)
let monster = Monster.getRootAsMonster(bb: fbb.sizedBuffer)
let values = monster.testarrayofbools
XCTAssertEqual(boolArray, values)
for i in 0..<monster.testarrayofboolsCount {
XCTAssertEqual(boolArray[Int(i)], monster.testarrayofbools(at: i))
}
}
func readMonster(fb: ByteBuffer) {
var monster = Monster.getRootAsMonster(bb: fb)
readFlatbufferMonster(monster: &monster)

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2021 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Foundation
import XCTest
@testable import FlatBuffers
class FlatBuffersMoreDefaults: XCTestCase {
func testFlatbuffersObject() {
var fbb = FlatBufferBuilder()
let root = MoreDefaults.createMoreDefaults(&fbb)
fbb.finish(offset: root)
let defaults = MoreDefaults.getRootAsMoreDefaults(bb: fbb.sizedBuffer)
XCTAssertEqual(defaults.emptyString, "")
XCTAssertEqual(defaults.someString, "some")
XCTAssertEqual(defaults.ints, [])
XCTAssertEqual(defaults.floats, [])
XCTAssertEqual(defaults.intsCount, 0)
XCTAssertEqual(defaults.floatsCount, 0)
}
func testFlatbuffersObjectAPI() {
var fbb = FlatBufferBuilder()
let defaults = MoreDefaultsT()
XCTAssertEqual(defaults.emptyString, "")
XCTAssertEqual(defaults.someString, "some")
XCTAssertEqual(defaults.ints, [])
XCTAssertEqual(defaults.floats, [])
let buffer = defaults.serialize(builder: &fbb, type: MoreDefaults.self)
let fDefaults = MoreDefaults.getRootAsMoreDefaults(bb: buffer)
XCTAssertEqual(fDefaults.emptyString, "")
XCTAssertEqual(fDefaults.someString, "some")
XCTAssertEqual(fDefaults.ints, [])
XCTAssertEqual(fDefaults.floats, [])
XCTAssertEqual(fDefaults.intsCount, 0)
XCTAssertEqual(fDefaults.floatsCount, 0)
}
}

View File

@@ -32,6 +32,7 @@ extension FlatBuffersMonsterWriterTests {
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__FlatBuffersMonsterWriterTests = [
("testArrayOfBools", testArrayOfBools),
("testCreateMonster", testCreateMonster),
("testCreateMonsterPrefixed", testCreateMonsterPrefixed),
("testCreateMonsterResizedBuffer", testCreateMonsterResizedBuffer),
@@ -43,6 +44,16 @@ extension FlatBuffersMonsterWriterTests {
]
}
extension FlatBuffersMoreDefaults {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__FlatBuffersMoreDefaults = [
("testFlatbuffersObject", testFlatbuffersObject),
("testFlatbuffersObjectAPI", testFlatbuffersObjectAPI),
]
}
extension FlatBuffersStructsTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
@@ -100,6 +111,7 @@ public func __allTests() -> [XCTestCaseEntry] {
[
testCase(FlatBuffersDoubleTests.__allTests__FlatBuffersDoubleTests),
testCase(FlatBuffersMonsterWriterTests.__allTests__FlatBuffersMonsterWriterTests),
testCase(FlatBuffersMoreDefaults.__allTests__FlatBuffersMoreDefaults),
testCase(FlatBuffersStructsTests.__allTests__FlatBuffersStructsTests),
testCase(FlatBuffersTests.__allTests__FlatBuffersTests),
testCase(FlatBuffersUnionTests.__allTests__FlatBuffersUnionTests),

View File

@@ -800,9 +800,9 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPIPacker {
public var testhashu64Fnv1a: UInt64 { let o = _accessor.offset(VTOFFSET.testhashu64Fnv1a.v); return o == 0 ? 0 : _accessor.readBuffer(of: UInt64.self, at: o) }
@discardableResult public func mutate(testhashu64Fnv1a: UInt64) -> Bool {let o = _accessor.offset(VTOFFSET.testhashu64Fnv1a.v); return _accessor.mutate(testhashu64Fnv1a, index: o) }
public var testarrayofboolsCount: Int32 { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return o == 0 ? 0 : _accessor.vector(count: o) }
public func testarrayofbools(at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return o == 0 ? true : 0 != _accessor.directRead(of: Byte.self, offset: _accessor.vector(at: o) + index * 1) }
public var testarrayofbools: [Byte] { return _accessor.getVector(at: VTOFFSET.testarrayofbools.v) ?? [] }
public func mutate(testarrayofbools: Byte, at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return _accessor.directMutate(testarrayofbools, index: _accessor.vector(at: o) + index * 1) }
public func testarrayofbools(at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return o == 0 ? true : _accessor.directRead(of: Bool.self, offset: _accessor.vector(at: o) + index * 1) }
public var testarrayofbools: [Bool] { return _accessor.getVector(at: VTOFFSET.testarrayofbools.v) ?? [] }
public func mutate(testarrayofbools: Bool, at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return _accessor.directMutate(testarrayofbools, index: _accessor.vector(at: o) + index * 1) }
public var testf: Float32 { let o = _accessor.offset(VTOFFSET.testf.v); return o == 0 ? 3.14159 : _accessor.readBuffer(of: Float32.self, at: o) }
@discardableResult public func mutate(testf: Float32) -> Bool {let o = _accessor.offset(VTOFFSET.testf.v); return _accessor.mutate(testf, index: o) }
public var testf2: Float32 { let o = _accessor.offset(VTOFFSET.testf2.v); return o == 0 ? 3.0 : _accessor.readBuffer(of: Float32.self, at: o) }

View File

@@ -0,0 +1,122 @@
// automatically generated by the FlatBuffers compiler, do not modify
// swiftlint:disable all
// swiftformat:disable all
import FlatBuffers
public struct MoreDefaults: FlatBufferObject, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func getRootAsMoreDefaults(bb: ByteBuffer) -> MoreDefaults { return MoreDefaults(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 ints = 4
case floats = 6
case emptyString = 8
case someString = 10
var v: Int32 { Int32(self.rawValue) }
var p: VOffset { self.rawValue }
}
public var intsCount: Int32 { let o = _accessor.offset(VTOFFSET.ints.v); return o == 0 ? 0 : _accessor.vector(count: o) }
public func ints(at index: Int32) -> Int32 { let o = _accessor.offset(VTOFFSET.ints.v); return o == 0 ? 0 : _accessor.directRead(of: Int32.self, offset: _accessor.vector(at: o) + index * 4) }
public var ints: [Int32] { return _accessor.getVector(at: VTOFFSET.ints.v) ?? [] }
public var floatsCount: Int32 { let o = _accessor.offset(VTOFFSET.floats.v); return o == 0 ? 0 : _accessor.vector(count: o) }
public func floats(at index: Int32) -> Float32 { let o = _accessor.offset(VTOFFSET.floats.v); return o == 0 ? 0 : _accessor.directRead(of: Float32.self, offset: _accessor.vector(at: o) + index * 4) }
public var floats: [Float32] { return _accessor.getVector(at: VTOFFSET.floats.v) ?? [] }
public var emptyString: String? { let o = _accessor.offset(VTOFFSET.emptyString.v); return o == 0 ? "" : _accessor.string(at: o) }
public var emptyStringSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.emptyString.v) }
public var someString: String? { let o = _accessor.offset(VTOFFSET.someString.v); return o == 0 ? "some" : _accessor.string(at: o) }
public var someStringSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.someString.v) }
public static func startMoreDefaults(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 4) }
public static func addVectorOf(ints: Offset<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: ints, at: VTOFFSET.ints.p) }
public static func addVectorOf(floats: Offset<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: floats, at: VTOFFSET.floats.p) }
public static func add(emptyString: Offset<String>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: emptyString, at: VTOFFSET.emptyString.p) }
public static func add(someString: Offset<String>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: someString, at: VTOFFSET.someString.p) }
public static func endMoreDefaults(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
public static func createMoreDefaults(
_ fbb: inout FlatBufferBuilder,
vectorOfInts ints: Offset<UOffset> = Offset(),
vectorOfFloats floats: Offset<UOffset> = Offset(),
offsetOfEmptyString emptyString: Offset<String> = Offset(),
offsetOfSomeString someString: Offset<String> = Offset()
) -> Offset<UOffset> {
let __start = MoreDefaults.startMoreDefaults(&fbb)
MoreDefaults.addVectorOf(ints: ints, &fbb)
MoreDefaults.addVectorOf(floats: floats, &fbb)
MoreDefaults.add(emptyString: emptyString, &fbb)
MoreDefaults.add(someString: someString, &fbb)
return MoreDefaults.endMoreDefaults(&fbb, start: __start)
}
public mutating func unpack() -> MoreDefaultsT {
return MoreDefaultsT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MoreDefaultsT?) -> Offset<UOffset> {
guard var obj = obj else { return Offset<UOffset>() }
return pack(&builder, obj: &obj)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MoreDefaultsT) -> Offset<UOffset> {
let __ints = builder.createVector(obj.ints)
let __floats = builder.createVector(obj.floats)
let __emptyString: Offset<String>
if let s = obj.emptyString {
__emptyString = builder.create(string: s)
} else {
__emptyString = Offset<String>()
}
let __someString: Offset<String>
if let s = obj.someString {
__someString = builder.create(string: s)
} else {
__someString = Offset<String>()
}
let __root = MoreDefaults.startMoreDefaults(&builder)
MoreDefaults.addVectorOf(ints: __ints, &builder)
MoreDefaults.addVectorOf(floats: __floats, &builder)
MoreDefaults.add(emptyString: __emptyString, &builder)
MoreDefaults.add(someString: __someString, &builder)
return MoreDefaults.endMoreDefaults(&builder, start: __root)
}
}
public class MoreDefaultsT: NativeObject {
public var ints: [Int32]
public var floats: [Float32]
public var emptyString: String?
public var someString: String?
public init(_ _t: inout MoreDefaults) {
ints = []
for index in 0..<_t.intsCount {
ints.append(_t.ints(at: index))
}
floats = []
for index in 0..<_t.floatsCount {
floats.append(_t.floats(at: index))
}
emptyString = _t.emptyString
someString = _t.someString
}
public init() {
ints = []
floats = []
emptyString = ""
someString = "some"
}
public func serialize() -> ByteBuffer { return serialize(type: MoreDefaults.self) }
}

View File

@@ -69,9 +69,10 @@ $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS $TEST_JS_TS_FLAGS -o namespace
working_dir=`pwd`
cd FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests
$working_dir/../flatc --swift --grpc $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -I ../../../include_test ../../../monster_test.fbs
$working_dir/../flatc --swift $TEST_BASE_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS ../../../union_vector/union_vector.fbs
$working_dir/../flatc --swift ../../../optional_scalars.fbs
$working_dir/../flatc --swift --grpc $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -I ${working_dir}/include_test ${working_dir}/monster_test.fbs
$working_dir/../flatc --swift $TEST_BASE_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS ${working_dir}/union_vector/union_vector.fbs
$working_dir/../flatc --swift ${working_dir}/optional_scalars.fbs
$working_dir/../flatc --swift --gen-object-api ${working_dir}/more_defaults.fbs
cd $working_dir
cd FlatBuffers.GRPC.Swift/Sources/Model