summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormustiikhalil <mustii@mmk.one>2021-05-14 20:59:28 +0300
committerGitHub <noreply@github.com>2021-05-14 20:59:28 +0300
commita5175c513a192ffd50fbfb1574817bb99b3e20cc (patch)
treeae8f4c3d6ac9637e809a588c85322fda6ce784ef
parent04b10f5a3a78aed27030a4e26dcf36921979114f (diff)
downloadflatbuffers-a5175c513a192ffd50fbfb1574817bb99b3e20cc.tar.gz
flatbuffers-a5175c513a192ffd50fbfb1574817bb99b3e20cc.tar.bz2
flatbuffers-a5175c513a192ffd50fbfb1574817bb99b3e20cc.zip
Implements verifier and code gen for swift (#6373)
Updates test cases on linux Adhere to new protocol naming Adds fuzzing Adds documentation Adds support for string unions Updated fuzzer generated code
-rw-r--r--.gitignore1
-rw-r--r--grpc/examples/swift/Greeter/Sources/Model/greeter_generated.swift16
-rw-r--r--src/idl_gen_swift.cpp142
-rw-r--r--swift.swiftformat1
-rw-r--r--swift/Sources/FlatBuffers/ByteBuffer.swift77
-rw-r--r--swift/Sources/FlatBuffers/Constants.swift30
-rw-r--r--swift/Sources/FlatBuffers/Enum.swift54
-rw-r--r--swift/Sources/FlatBuffers/FlatBufferBuilder.swift49
-rw-r--r--swift/Sources/FlatBuffers/FlatBufferObject.swift23
-rw-r--r--swift/Sources/FlatBuffers/FlatBuffersUtils.swift7
-rw-r--r--swift/Sources/FlatBuffers/FlatbuffersErrors.swift59
-rw-r--r--swift/Sources/FlatBuffers/Message.swift4
-rw-r--r--swift/Sources/FlatBuffers/NativeObject.swift8
-rw-r--r--swift/Sources/FlatBuffers/Root.swift68
-rw-r--r--swift/Sources/FlatBuffers/String+extension.swift48
-rw-r--r--swift/Sources/FlatBuffers/Struct.swift14
-rw-r--r--swift/Sources/FlatBuffers/Table.swift76
-rw-r--r--swift/Sources/FlatBuffers/TableVerifier.swift202
-rw-r--r--swift/Sources/FlatBuffers/VeriferOptions.swift52
-rw-r--r--swift/Sources/FlatBuffers/Verifiable.swift211
-rw-r--r--swift/Sources/FlatBuffers/Verifier.swift199
-rw-r--r--tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift16
-rw-r--r--tests/FlatBuffers.Test.Swift/Package.swift4
-rw-r--r--tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/fuzzer.fbs32
-rw-r--r--tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/fuzzer_generated.swift224
-rw-r--r--tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/main.swift15
-rwxr-xr-xtests/FlatBuffers.Test.Swift/SwiftTest.sh12
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift69
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersTests.swift36
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift59
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersVectorsTests.swift12
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersDoubleTests.swift36
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersVerifierTests.swift238
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift32
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift200
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/more_defaults_generated.swift16
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/optional_scalars_generated.swift46
-rw-r--r--tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift71
38 files changed, 2291 insertions, 168 deletions
diff --git a/.gitignore b/.gitignore
index 70a88b58..a70372ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -141,3 +141,4 @@ yarn-error.log
**/vendor
**/go.sum
flatbuffers.pc
+**/FlatBuffers.Test.Swift.xcodeproj
diff --git a/grpc/examples/swift/Greeter/Sources/Model/greeter_generated.swift b/grpc/examples/swift/Greeter/Sources/Model/greeter_generated.swift
index 8914d983..bc1eca3c 100644
--- a/grpc/examples/swift/Greeter/Sources/Model/greeter_generated.swift
+++ b/grpc/examples/swift/Greeter/Sources/Model/greeter_generated.swift
@@ -4,7 +4,7 @@
import FlatBuffers
-public struct models_HelloReply: FlatBufferObject {
+public struct models_HelloReply: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -34,9 +34,15 @@ public struct models_HelloReply: FlatBufferObject {
models_HelloReply.add(message: message, &fbb)
return models_HelloReply.endHelloReply(&fbb, start: __start)
}
+
+ 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.message.p, fieldName: "message", required: false, type: ForwardOffset<String>.self)
+ _v.finish()
+ }
}
-public struct models_HelloRequest: FlatBufferObject {
+public struct models_HelloRequest: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -66,5 +72,11 @@ public struct models_HelloRequest: FlatBufferObject {
models_HelloRequest.add(name: name, &fbb)
return models_HelloRequest.endHelloRequest(&fbb, start: __start)
}
+
+ 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.name.p, fieldName: "name", required: false, type: ForwardOffset<String>.self)
+ _v.finish()
+ }
}
diff --git a/src/idl_gen_swift.cpp b/src/idl_gen_swift.cpp
index 3fffd394..762cd291 100644
--- a/src/idl_gen_swift.cpp
+++ b/src/idl_gen_swift.cpp
@@ -187,7 +187,8 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
GenComment(struct_def.doc_comment);
code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
- code_ += "{{ACCESS_TYPE}} struct {{STRUCTNAME}}: NativeStruct\\";
+ code_ +=
+ "{{ACCESS_TYPE}} struct {{STRUCTNAME}}: NativeStruct, Verifiable\\";
if (parser_.opts.generate_object_based_api) code_ += ", NativeObject\\";
code_ += " {";
code_ += "";
@@ -250,6 +251,15 @@ class SwiftGenerator : public BaseGenerator {
GenReaderMainBody() + "{{VALUETYPE}}(rawValue: _{{VALUENAME}})! }";
}
}
+ code_ += "";
+ code_ +=
+ "public static func verify<T>(_ verifier: inout Verifier, at position: "
+ "Int, of type: T.Type) throws where T: Verifiable {";
+ Indent();
+ code_ +=
+ "try verifier.inBuffer(position: position, of: {{STRUCTNAME}}.self)";
+ Outdent();
+ code_ += "}";
Outdent();
code_ += "}\n";
}
@@ -375,6 +385,8 @@ class SwiftGenerator : public BaseGenerator {
GenTableWriter(struct_def);
if (parser_.opts.generate_object_based_api)
GenerateObjectAPITableExtension(struct_def);
+ code_ += "";
+ GenerateVerifier(struct_def);
Outdent();
code_ += "}\n";
}
@@ -410,6 +422,7 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("MUTABLE", struct_def.fixed ? Mutable() : "");
code_ +=
"{{ACCESS_TYPE}} struct {{STRUCTNAME}}{{MUTABLE}}: FlatBufferObject\\";
+ if (!struct_def.fixed) code_ += ", Verifiable\\";
if (!struct_def.fixed && parser_.opts.generate_object_based_api)
code_ += ", ObjectAPIPacker\\";
code_ += " {\n";
@@ -651,8 +664,10 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("VALUETYPE", type);
code_.SetValue("OFFSET", name);
code_.SetValue("CONSTANT", field.value.constant);
- std::string def_Val = field.IsDefault() ? "{{CONSTANT}}" : "nil";
- std::string optional = field.IsOptional() ? "?" : "";
+ bool opt_scalar =
+ field.IsOptional() && IsScalar(field.value.type.base_type);
+ std::string def_Val = opt_scalar ? "nil" : "{{CONSTANT}}";
+ std::string optional = opt_scalar ? "?" : "";
auto const_string = "return o == 0 ? " + def_Val + " : ";
GenComment(field.doc_comment);
if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) &&
@@ -831,6 +846,112 @@ class SwiftGenerator : public BaseGenerator {
}
}
+ void GenerateVerifier(const StructDef &struct_def) {
+ code_ +=
+ "public 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)";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto offset = NumToString(field.value.offset);
+ auto name = Name(field);
+
+ code_.SetValue("VALUENAME", name);
+ code_.SetValue("VALUETYPE", GenerateVerifierType(field));
+ code_.SetValue("OFFSET", name);
+ code_.SetValue("ISREQUIRED", field.IsRequired() ? "true" : "false");
+
+ if (IsUnion(field.value.type)) {
+ GenerateUnionTypeVerifier(field);
+ continue;
+ }
+
+ code_ +=
+ "try _v.visit(field: {{TABLEOFFSET}}.{{OFFSET}}.p, fieldName: "
+ "\"{{VALUENAME}}\", required: {{ISREQUIRED}}, type: "
+ "{{VALUETYPE}}.self)";
+ }
+ code_ += "_v.finish()";
+ Outdent();
+ code_ += "}";
+ }
+
+ void GenerateUnionTypeVerifier(const FieldDef &field) {
+ auto is_vector = IsVector(field.value.type) || IsArray(field.value.type);
+ if (field.value.type.base_type == BASE_TYPE_UTYPE ||
+ (is_vector &&
+ field.value.type.VectorType().base_type == BASE_TYPE_UTYPE))
+ return;
+ EnumDef &union_def = *field.value.type.enum_def;
+ code_.SetValue("VALUETYPE", NameWrappedInNameSpace(union_def));
+ code_.SetValue("FUNCTION_NAME", is_vector ? "visitUnionVector" : "visit");
+ code_ +=
+ "try _v.{{FUNCTION_NAME}}(unionKey: {{TABLEOFFSET}}.{{OFFSET}}Type.p, "
+ "unionField: {{TABLEOFFSET}}.{{OFFSET}}.p, unionKeyName: "
+ "\"{{VALUENAME}}Type\", fieldName: \"{{VALUENAME}}\", required: "
+ "{{ISREQUIRED}}, completion: { (verifier, key: {{VALUETYPE}}, pos) in";
+ Indent();
+ code_ += "switch key {";
+ for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+
+ auto name = Name(ev);
+ auto type = GenType(ev.union_type);
+ code_.SetValue("KEY", name);
+ code_.SetValue("VALUETYPE", type);
+ code_ += "case .{{KEY}}:";
+ Indent();
+ if (ev.union_type.base_type == BASE_TYPE_NONE) {
+ code_ += "break // NOTE - SWIFT doesnt support none";
+ } else if (ev.union_type.base_type == BASE_TYPE_STRING) {
+ code_ +=
+ "try ForwardOffset<String>.verify(&verifier, at: pos, of: "
+ "String.self)";
+ } else {
+ code_.SetValue("MAINTYPE", ev.union_type.struct_def->fixed
+ ? type
+ : "ForwardOffset<" + type + ">");
+ code_ +=
+ "try {{MAINTYPE}}.verify(&verifier, at: pos, of: "
+ "{{VALUETYPE}}.self)";
+ }
+ Outdent();
+ }
+ code_ += "}";
+ Outdent();
+ code_ += "})";
+ }
+
+ std::string GenerateVerifierType(const FieldDef &field) {
+ auto type = field.value.type;
+ auto is_vector = IsVector(type) || IsArray(type);
+
+ if (is_vector) {
+ auto vector_type = field.value.type.VectorType();
+ return "ForwardOffset<Vector<" +
+ GenerateNestedVerifierTypes(vector_type) + ", " +
+ GenType(vector_type) + ">>";
+ }
+
+ return GenerateNestedVerifierTypes(field.value.type);
+ }
+
+ std::string GenerateNestedVerifierTypes(const Type &type) {
+ auto string_type = GenType(type);
+
+ if (IsScalar(type.base_type)) { return string_type; }
+
+ if (IsString(type)) { return "ForwardOffset<" + string_type + ">"; }
+
+ if (type.struct_def && type.struct_def->fixed) { return string_type; }
+
+ return "ForwardOffset<" + string_type + ">";
+ }
+
void GenByKeyFunctions(const FieldDef &key_field) {
code_.SetValue("TYPE", GenType(key_field.value.type));
code_ +=
@@ -844,13 +965,24 @@ class SwiftGenerator : public BaseGenerator {
void GenEnum(const EnumDef &enum_def) {
if (enum_def.generated) return;
auto is_private_access = enum_def.attributes.Lookup("private");
+ code_.SetValue("ENUM_TYPE",
+ enum_def.is_union ? "UnionEnum" : "Enum, Verifiable");
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
code_.SetValue("ENUM_NAME", NameWrappedInNameSpace(enum_def));
code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
GenComment(enum_def.doc_comment);
- code_ += "{{ACCESS_TYPE}} enum {{ENUM_NAME}}: {{BASE_TYPE}}, Enum {";
+ code_ +=
+ "{{ACCESS_TYPE}} enum {{ENUM_NAME}}: {{BASE_TYPE}}, {{ENUM_TYPE}} {";
Indent();
code_ += "{{ACCESS_TYPE}} typealias T = {{BASE_TYPE}}";
+ if (enum_def.is_union) {
+ code_ += "";
+ code_ += "{{ACCESS_TYPE}} init?(value: T) {";
+ Indent();
+ code_ += "self.init(rawValue: value)";
+ Outdent();
+ code_ += "}\n";
+ }
code_ +=
"{{ACCESS_TYPE}} static var byteSize: Int { return "
"MemoryLayout<{{BASE_TYPE}}>.size "
@@ -865,7 +997,7 @@ class SwiftGenerator : public BaseGenerator {
GenComment(ev.doc_comment);
code_ += "case {{KEY}} = {{VALUE}}";
}
- code_ += "\n";
+ code_ += "";
AddMinOrMaxEnumValue(Name(*enum_def.MaxValue()), "max");
AddMinOrMaxEnumValue(Name(*enum_def.MinValue()), "min");
Outdent();
diff --git a/swift.swiftformat b/swift.swiftformat
index 8ef724df..3f4c45d1 100644
--- a/swift.swiftformat
+++ b/swift.swiftformat
@@ -2,6 +2,7 @@
# format
--indent 2
+--maxwidth 80
# options
--self remove # redundantSelf
diff --git a/swift/Sources/FlatBuffers/ByteBuffer.swift b/swift/Sources/FlatBuffers/ByteBuffer.swift
index b301e02e..c658d467 100644
--- a/swift/Sources/FlatBuffers/ByteBuffer.swift
+++ b/swift/Sources/FlatBuffers/ByteBuffer.swift
@@ -16,6 +16,9 @@
import Foundation
+/// `ByteBuffer` is the interface that stores the data for a `Flatbuffers` object
+/// it allows users to write and read data directly from memory thus the use of its
+/// functions should be used
@frozen
public struct ByteBuffer {
@@ -32,7 +35,9 @@ public struct ByteBuffer {
@usableFromInline
init(count: Int, alignment: Int) {
- memory = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: alignment)
+ memory = UnsafeMutableRawPointer.allocate(
+ byteCount: count,
+ alignment: alignment)
capacity = count
unowned = false
}
@@ -69,7 +74,7 @@ public struct ByteBuffer {
/// Reallocates the buffer incase the object to be written doesnt fit in the current buffer
/// - Parameter size: Size of the current object
@usableFromInline
- internal func reallocate(_ size: Int, writerSize: Int, alignment: Int) {
+ func reallocate(_ size: Int, writerSize: Int, alignment: Int) {
let currentWritingIndex = capacity &- writerSize
while capacity <= writerSize &+ size {
capacity = capacity << 1
@@ -78,7 +83,9 @@ public struct ByteBuffer {
/// solution take from Apple-NIO
capacity = capacity.convertToPowerofTwo
- let newData = UnsafeMutableRawPointer.allocate(byteCount: capacity, alignment: alignment)
+ let newData = UnsafeMutableRawPointer.allocate(
+ byteCount: capacity,
+ alignment: alignment)
memset(newData, 0, capacity &- writerSize)
memcpy(
newData.advanced(by: capacity &- writerSize),
@@ -94,9 +101,9 @@ public struct ByteBuffer {
/// The size of the elements written to the buffer + their paddings
private var _writerSize: Int = 0
/// Aliginment of the current memory being written to the buffer
- internal var alignment = 1
+ var alignment = 1
/// Current Index which is being used to write to the buffer, it is written from the end to the start of the buffer
- internal var writerIndex: Int { _storage.capacity &- _writerSize }
+ var writerIndex: Int { _storage.capacity &- _writerSize }
/// Reader is the position of the current Writer Index (capacity - size)
public var reader: Int { writerIndex }
@@ -166,7 +173,7 @@ public struct ByteBuffer {
/// - Parameters:
/// - memory: Current memory of the buffer
/// - count: count of bytes
- internal init(memory: UnsafeMutableRawPointer, count: Int) {
+ init(memory: UnsafeMutableRawPointer, count: Int) {
_storage = Storage(count: count, alignment: alignment)
_storage.copy(from: memory, count: count)
_writerSize = _storage.capacity
@@ -177,7 +184,11 @@ public struct ByteBuffer {
/// - memory: Current memory of the buffer
/// - count: count of bytes
/// - removeBytes: Removes a number of bytes from the current size
- internal init(memory: UnsafeMutableRawPointer, count: Int, removing removeBytes: Int) {
+ init(
+ memory: UnsafeMutableRawPointer,
+ count: Int,
+ removing removeBytes: Int)
+ {
_storage = Storage(count: count, alignment: alignment)
_storage.copy(from: memory, count: count)
_writerSize = removeBytes
@@ -247,7 +258,7 @@ public struct ByteBuffer {
/// - bytes: Pointer to the view
/// - len: Size of string
@inline(__always)
- mutating internal func push(
+ mutating func push(
bytes: UnsafeBufferPointer<String.UTF8View.Element>,
len: Int) -> Bool
{
@@ -292,20 +303,18 @@ public struct ByteBuffer {
/// pops the written VTable if it's already written into the buffer
/// - Parameter size: size of the `VTable`
@inline(__always)
- mutating internal func pop(_ size: Int) {
+ mutating func pop(_ size: Int) {
assert((_writerSize &- size) > 0, "New size should NOT be a negative number")
memset(_storage.memory.advanced(by: writerIndex), 0, _writerSize &- size)
_writerSize = size
}
/// Clears the current size of the buffer
- @inline(__always)
mutating public func clearSize() {
_writerSize = 0
}
/// Clears the current instance of the buffer, replacing it with new memory
- @inline(__always)
mutating public func clear() {
_writerSize = 0
alignment = 1
@@ -317,10 +326,7 @@ public struct ByteBuffer {
/// - def: Type of the object
/// - position: the index of the object in the buffer
public func read<T>(def: T.Type, position: Int) -> T {
- assert(
- position + MemoryLayout<T>.size <= _storage.capacity,
- "Reading out of bounds is illegal")
- return _storage.memory.advanced(by: position).load(as: T.self)
+ _storage.memory.advanced(by: position).load(as: T.self)
}
/// Reads a slice from the memory assuming a type of T
@@ -329,14 +335,14 @@ public struct ByteBuffer {
/// - count: count of bytes in memory
@inline(__always)
public func readSlice<T>(
- index: Int32,
- count: Int32) -> [T]
+ index: Int,
+ count: Int) -> [T]
{
- let _index = Int(index)
- let _count = Int(count)
- assert(_index + _count <= _storage.capacity, "Reading out of bounds is illegal")
- let start = _storage.memory.advanced(by: _index).assumingMemoryBound(to: T.self)
- let array = UnsafeBufferPointer(start: start, count: _count)
+ assert(
+ index + count <= _storage.capacity,
+ "Reading out of bounds is illegal")
+ let start = _storage.memory.advanced(by: index).assumingMemoryBound(to: T.self)
+ let array = UnsafeBufferPointer(start: start, count: count)
return Array(array)
}
@@ -345,17 +351,16 @@ public struct ByteBuffer {
/// - index: index of the string in the buffer
/// - count: length of the string
/// - type: Encoding of the string
- @inline(__always)
public func readString(
- at index: Int32,
- count: Int32,
+ at index: Int,
+ count: Int,
type: String.Encoding = .utf8) -> String?
{
- let _index = Int(index)
- let _count = Int(count)
- assert(_index + _count <= _storage.capacity, "Reading out of bounds is illegal")
- let start = _storage.memory.advanced(by: _index).assumingMemoryBound(to: UInt8.self)
- let bufprt = UnsafeBufferPointer(start: start, count: _count)
+ assert(
+ index + count <= _storage.capacity,
+ "Reading out of bounds is illegal")
+ let start = _storage.memory.advanced(by: index).assumingMemoryBound(to: UInt8.self)
+ let bufprt = UnsafeBufferPointer(start: start, count: count)
return String(bytes: Array(bufprt), encoding: type)
}
@@ -363,12 +368,22 @@ public struct ByteBuffer {
/// - Parameter removeBytes: the amount of bytes to remove from the current Size
public func duplicate(removing removeBytes: Int = 0) -> ByteBuffer {
assert(removeBytes > 0, "Can NOT remove negative bytes")
- assert(removeBytes < _storage.capacity, "Can NOT remove more bytes than the ones allocated")
+ assert(
+ removeBytes < _storage.capacity,
+ "Can NOT remove more bytes than the ones allocated")
return ByteBuffer(
memory: _storage.memory,
count: _storage.capacity,
removing: _writerSize &- removeBytes)
}
+
+ /// SkipPrefix Skips the first 4 bytes in case one of the following
+ /// functions are called `getPrefixedSizeCheckedRoot` & `getPrefixedSizeRoot`
+ /// which allows us to skip the first 4 bytes instead of recreating the buffer
+ @usableFromInline
+ mutating func skipPrefix() {
+ _writerSize = _writerSize &- MemoryLayout<Int32>.size
+ }
}
extension ByteBuffer: CustomDebugStringConvertible {
diff --git a/swift/Sources/FlatBuffers/Constants.swift b/swift/Sources/FlatBuffers/Constants.swift
index 470b7252..50a58178 100644
--- a/swift/Sources/FlatBuffers/Constants.swift
+++ b/swift/Sources/FlatBuffers/Constants.swift
@@ -32,14 +32,16 @@ public typealias VOffset = UInt16
/// Maximum size for a buffer
public let FlatBufferMaxSize = UInt32.max << ((MemoryLayout<SOffset>.size * 8 - 1) - 1)
-/// Protocol that confirms all the numbers
+/// Protocol that All Scalars should conform to
///
-/// Scalar is used to confirm all the numbers that can be represented in a FlatBuffer. It's used to write/read from the buffer.
+/// Scalar is used to conform all the numbers that can be represented in a FlatBuffer. It's used to write/read from the buffer.
public protocol Scalar: Equatable {
associatedtype NumericValue
var convertedEndian: NumericValue { get }
}
+extension Scalar where Self: Verifiable {}
+
extension Scalar where Self: FixedWidthInteger {
/// Converts the value from BigEndian to LittleEndian
///
@@ -49,7 +51,7 @@ extension Scalar where Self: FixedWidthInteger {
}
}
-extension Double: Scalar {
+extension Double: Scalar, Verifiable {
public typealias NumericValue = UInt64
public var convertedEndian: UInt64 {
@@ -57,7 +59,7 @@ extension Double: Scalar {
}
}
-extension Float32: Scalar {
+extension Float32: Scalar, Verifiable {
public typealias NumericValue = UInt32
public var convertedEndian: UInt32 {
@@ -65,7 +67,7 @@ extension Float32: Scalar {
}
}
-extension Bool: Scalar {
+extension Bool: Scalar, Verifiable {
public var convertedEndian: UInt8 {
self == true ? 1 : 0
}
@@ -73,39 +75,39 @@ extension Bool: Scalar {
public typealias NumericValue = UInt8
}
-extension Int: Scalar {
+extension Int: Scalar, Verifiable {
public typealias NumericValue = Int
}
-extension Int8: Scalar {
+extension Int8: Scalar, Verifiable {
public typealias NumericValue = Int8
}
-extension Int16: Scalar {
+extension Int16: Scalar, Verifiable {
public typealias NumericValue = Int16
}
-extension Int32: Scalar {
+extension Int32: Scalar, Verifiable {
public typealias NumericValue = Int32
}
-extension Int64: Scalar {
+extension Int64: Scalar, Verifiable {
public typealias NumericValue = Int64
}
-extension UInt8: Scalar {
+extension UInt8: Scalar, Verifiable {
public typealias NumericValue = UInt8
}
-extension UInt16: Scalar {
+extension UInt16: Scalar, Verifiable {
public typealias NumericValue = UInt16
}
-extension UInt32: Scalar {
+extension UInt32: Scalar, Verifiable {
public typealias NumericValue = UInt32
}
-extension UInt64: Scalar {
+extension UInt64: Scalar, Verifiable {
public typealias NumericValue = UInt64
}
diff --git a/swift/Sources/FlatBuffers/Enum.swift b/swift/Sources/FlatBuffers/Enum.swift
new file mode 100644
index 00000000..f8cbebb1
--- /dev/null
+++ b/swift/Sources/FlatBuffers/Enum.swift
@@ -0,0 +1,54 @@
+/*
+ * 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
+
+/// Enum is a protocol that all flatbuffers enums should conform to
+/// Since it allows us to get the actual `ByteSize` and `Value`
+public protocol Enum {
+ /// associatedtype that the type of the enum should conform to
+ associatedtype T: Scalar & Verifiable
+ /// Size of the current associatedtype in the enum
+ static var byteSize: Int { get }
+ /// The current value the enum hosts
+ var value: T { get }
+}
+
+extension Enum where Self: Verifiable {
+
+ /// Verifies that the current value is which the bounds of the buffer, and if
+ /// the current `Value` is aligned properly
+ /// - Parameters:
+ /// - verifier: Verifier that hosts the buffer
+ /// - position: Current position within the buffer
+ /// - type: The type of the object to be verified
+ /// - Throws: Errors coming from `inBuffer` function
+ public static func verify<T>(
+ _ verifier: inout Verifier,
+ at position: Int,
+ of type: T.Type) throws where T: Verifiable
+ {
+ try verifier.inBuffer(position: position, of: type.self)
+ }
+
+}
+
+/// UnionEnum is a Protocol that allows us to create Union type of enums
+/// and their value initializers. Since an `init` was required by
+/// the verifier
+public protocol UnionEnum: Enum {
+ init?(value: T) throws
+}
diff --git a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift
index 9a166bac..71b71399 100644
--- a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift
+++ b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift
@@ -16,6 +16,9 @@
import Foundation
+/// `FlatBufferBuilder` builds a `FlatBuffer` through manipulating its internal state.
+/// This is done by creating a `ByteBuffer` that hosts the incoming data and
+/// has a hardcoded growth limit of `2GiB` which is set by the Flatbuffers standards
@frozen
public struct FlatBufferBuilder {
@@ -74,7 +77,9 @@ public struct FlatBufferBuilder {
/// Returns A sized Buffer from the readable bytes
public var sizedBuffer: ByteBuffer {
assert(finished, "Data shouldn't be called before finish()")
- return ByteBuffer(memory: _bb.memory.advanced(by: _bb.reader), count: Int(_bb.size))
+ return ByteBuffer(
+ memory: _bb.memory.advanced(by: _bb.reader),
+ count: Int(_bb.size))
}
// MARK: - Init
@@ -112,7 +117,9 @@ public struct FlatBufferBuilder {
for field in fields {
let start = _bb.capacity &- Int(table.o)
let startTable = start &- Int(_bb.read(def: Int32.self, position: start))
- let isOkay = _bb.read(def: VOffset.self, position: startTable &+ Int(field)) != 0
+ let isOkay = _bb.read(
+ def: VOffset.self,
+ position: startTable &+ Int(field)) != 0
assert(isOkay, "Flatbuffers requires the following field")
}
}
@@ -122,9 +129,15 @@ public struct FlatBufferBuilder {
/// - offset: Offset of the table
/// - fileId: Takes the fileId
/// - prefix: if false it wont add the size of the buffer
- mutating public func finish(offset: Offset, fileId: String, addPrefix prefix: Bool = false) {
+ mutating public func finish(
+ offset: Offset,
+ fileId: String,
+ addPrefix prefix: Bool = false)
+ {
let size = MemoryLayout<UOffset>.size
- preAlign(len: size &+ (prefix ? size : 0) &+ FileIdLength, alignment: _minAlignment)
+ preAlign(
+ len: size &+ (prefix ? size : 0) &+ FileIdLength,
+ alignment: _minAlignment)
assert(fileId.count == FileIdLength, "Flatbuffers requires file id to be 4")
_bb.push(string: fileId, len: 4)
finish(offset: offset, addPrefix: prefix)
@@ -134,7 +147,10 @@ public struct FlatBufferBuilder {
/// - Parameters:
/// - offset: Offset of the table
/// - prefix: if false it wont add the size of the buffer
- mutating public func finish(offset: Offset, addPrefix prefix: Bool = false) {
+ mutating public func finish(
+ offset: Offset,
+ addPrefix prefix: Bool = false)
+ {
notNested()
let size = MemoryLayout<UOffset>.size
preAlign(len: size &+ (prefix ? size : 0), alignment: _minAlignment)
@@ -184,7 +200,10 @@ public struct FlatBufferBuilder {
itr = itr &+ _vtableStorage.size
guard loaded.offset != 0 else { continue }
let _index = (_bb.writerIndex &+ Int(loaded.position))
- _bb.write(value: VOffset(vTableOffset &- loaded.offset), index: _index, direct: true)
+ _bb.write(
+ value: VOffset(vTableOffset &- loaded.offset),
+ index: _index,
+ direct: true)
}
_vtableStorage.clear()
@@ -375,7 +394,9 @@ public struct FlatBufferBuilder {
/// - Parameter structs: A vector of structs
/// - Returns: offset of the vector
mutating public func createVector<T: NativeStruct>(ofStructs structs: [T]) -> Offset {
- startVector(structs.count * MemoryLayout<T>.size, elementSize: MemoryLayout<T>.alignment)
+ startVector(
+ structs.count * MemoryLayout<T>.size,
+ elementSize: MemoryLayout<T>.alignment)
for i in structs.reversed() {
_ = create(struct: i)
}
@@ -394,7 +415,9 @@ public struct FlatBufferBuilder {
struct s: T, position: VOffset) -> Offset
{
let offset = create(struct: s)
- _vtableStorage.add(loc: FieldLoc(offset: _bb.size, position: VOffset(position)))
+ _vtableStorage.add(loc: FieldLoc(
+ offset: _bb.size,
+ position: VOffset(position)))
return offset
}
@@ -529,8 +552,6 @@ extension FlatBufferBuilder: CustomDebugStringConvertible {
var numOfFields: Int = 0
/// Last written Index
var writtenIndex: Int = 0
- /// the amount of added elements into the buffer
- var addedElements: Int { capacity - (numOfFields &* size) }
/// Creates the memory to store the buffer in
@usableFromInline
@@ -555,7 +576,9 @@ extension FlatBufferBuilder: CustomDebugStringConvertible {
/// and max offset
/// - Parameter loc: Location of encoded element
func add(loc: FieldLoc) {
- memory.baseAddress?.advanced(by: writtenIndex).storeBytes(of: loc, as: FieldLoc.self)
+ memory.baseAddress?.advanced(by: writtenIndex).storeBytes(
+ of: loc,
+ as: FieldLoc.self)
writtenIndex = writtenIndex &+ size
numOfFields = numOfFields &+ 1
maxOffset = max(loc.position, maxOffset)
@@ -574,7 +597,9 @@ extension FlatBufferBuilder: CustomDebugStringConvertible {
func ensure(space: Int) {
guard space &+ writtenIndex > capacity else { return }
memory.deallocate()
- memory = UnsafeMutableRawBufferPointer.allocate(byteCount: space, alignment: size)
+ memory = UnsafeMutableRawBufferPointer.allocate(
+ byteCount: space,
+ alignment: size)
capacity = space
}
diff --git a/swift/Sources/FlatBuffers/FlatBufferObject.swift b/swift/Sources/FlatBuffers/FlatBufferObject.swift
index 72325e79..cea3911e 100644
--- a/swift/Sources/FlatBuffers/FlatBufferObject.swift
+++ b/swift/Sources/FlatBuffers/FlatBufferObject.swift
@@ -31,15 +31,26 @@ public protocol FlatBufferObject: FlatbuffersInitializable {
var __buffer: ByteBuffer! { get }
}
+/// `ObjectAPIPacker` is a protocol that allows object to pack and unpack from a
+/// `NativeObject` to a flatbuffers Object and vice versa.
public protocol ObjectAPIPacker {
+ /// associatedtype to the object that should be unpacked.
associatedtype T
+
+ /// `pack` tries packs the variables of a native Object into the `ByteBuffer` by using
+ /// the FlatBufferBuilder
+ /// - Parameters:
+ /// - builder: FlatBufferBuilder that will host incoming data
+ /// - obj: Object of associatedtype to the current implementer
static func pack(_ builder: inout FlatBufferBuilder, obj: inout T?) -> Offset
+
+ /// `pack` packs the variables of a native Object into the `ByteBuffer` by using
+ /// the FlatBufferBuilder
+ /// - Parameters:
+ /// - builder: FlatBufferBuilder that will host incoming data
+ /// - obj: Object of associatedtype to the current implementer
static func pack(_ builder: inout FlatBufferBuilder, obj: inout T) -> Offset
- mutating func unpack() -> T
-}
-public protocol Enum {
- associatedtype T: Scalar
- static var byteSize: Int { get }
- var value: T { get }
+ /// `Unpack` unpacks a flatbuffers object into a `NativeObject`
+ mutating func unpack() -> T
}
diff --git a/swift/Sources/FlatBuffers/FlatBuffersUtils.swift b/swift/Sources/FlatBuffers/FlatBuffersUtils.swift
index f0a96dbd..2ab68fd2 100644
--- a/swift/Sources/FlatBuffers/FlatBuffersUtils.swift
+++ b/swift/Sources/FlatBuffers/FlatBuffersUtils.swift
@@ -16,7 +16,8 @@
import Foundation
-public final class FlatBuffersUtils {
+/// FlatBuffersUtils hosts some utility functions that might be useful
+public enum FlatBuffersUtils {
/// Gets the size of the prefix
/// - Parameter bb: Flatbuffer object
@@ -24,7 +25,9 @@ public final class FlatBuffersUtils {
bb.read(def: Int32.self, position: bb.reader)
}
- /// Removes the prefix by duplicating the Flatbuffer
+ /// Removes the prefix by duplicating the Flatbuffer this call is expensive since its
+ /// creates a new buffer use `readPrefixedSizeCheckedRoot` instead
+ /// unless a completely new buffer is required
/// - Parameter bb: Flatbuffer object
public static func removeSizePrefix(bb: ByteBuffer) -> ByteBuffer {
bb.duplicate(removing: MemoryLayout<Int32>.size)
diff --git a/swift/Sources/FlatBuffers/FlatbuffersErrors.swift b/swift/Sources/FlatBuffers/FlatbuffersErrors.swift
new file mode 100644
index 00000000..97188e9e
--- /dev/null
+++ b/swift/Sources/FlatBuffers/FlatbuffersErrors.swift
@@ -0,0 +1,59 @@
+/*
+ * 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
+
+/// Collection of thrown from the Flatbuffer verifier
+public enum FlatbuffersErrors: Error, Equatable {
+
+ /// Thrown when buffer is bigger than the allowed 2GiB
+ case exceedsMaxSizeAllowed
+ /// Thrown when there is an missaligned pointer at position
+ /// of type
+ case missAlignedPointer(position: Int, type: String)
+ /// Thrown when trying to read a value that goes out of the
+ /// current buffer bounds
+ case outOfBounds(position: UInt, end: Int)
+ /// Thrown when the signed offset is out of the bounds of the
+ /// current buffer
+ case signedOffsetOutOfBounds(offset: Int, position: Int)
+ /// Thrown when a required field doesnt exist within the buffer
+ case requiredFieldDoesntExist(position: VOffset, name: String)
+ /// Thrown when a string is missing its NULL Terminator `\0`,
+ /// this can be disabled in the `VerifierOptions`
+ case missingNullTerminator(position: Int, str: String?)
+ /// Thrown when the verifier has reached the maximum tables allowed,
+ /// this can be disabled in the `VerifierOptions`
+ case maximumTables
+ /// Thrown when the verifier has reached the maximum depth allowed,
+ /// this can be disabled in the `VerifierOptions`
+ case maximumDepth
+ /// Thrown when the verifier is presented with an unknown union case
+ case unknownUnionCase
+ /// thrown when a value for a union is not found within the buffer
+ case valueNotFound(key: Int?, keyName: String, field: Int?, fieldName: String)
+ /// thrown when the size of the keys vector doesnt match fields vector
+ case unionVectorSize(
+ keyVectorSize: Int,
+ fieldVectorSize: Int,
+ unionKeyName: String,
+ fieldName: String)
+ case apparentSizeTooLarge
+
+ public static func == (lhs: FlatbuffersErrors, rhs: FlatbuffersErrors) -> Bool {
+ lhs.localizedDescription == rhs.localizedDescription
+ }
+}
diff --git a/swift/Sources/FlatBuffers/Message.swift b/swift/Sources/FlatBuffers/Message.swift
index 52ae487b..76b7a622 100644
--- a/swift/Sources/FlatBuffers/Message.swift
+++ b/swift/Sources/FlatBuffers/Message.swift
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+import Foundation
+
+/// FlatBufferGRPCMessage protocol that should allow us to invoke
+/// initializers directly from the GRPC generated code
public protocol FlatBufferGRPCMessage {
/// Raw pointer which would be pointing to the beginning of the readable bytes
diff --git a/swift/Sources/FlatBuffers/NativeObject.swift b/swift/Sources/FlatBuffers/NativeObject.swift
index 2f360f0c..724c2eba 100644
--- a/swift/Sources/FlatBuffers/NativeObject.swift
+++ b/swift/Sources/FlatBuffers/NativeObject.swift
@@ -16,6 +16,9 @@
import Foundation
+/// NativeObject is a protocol that all of the `Object-API` generated code should be
+/// conforming to since it allows developers the ease of use to pack and unpack their
+/// Flatbuffers objects
public protocol NativeObject {}
extension NativeObject {
@@ -36,7 +39,10 @@ extension NativeObject {
/// - Returns: returns the encoded sized ByteBuffer
/// - Note: The `serialize(builder:type)` can be considered as a function that allows you to create smaller builder instead of the default `1024`.
/// It can be considered less expensive in terms of memory allocation
- public func serialize<T: ObjectAPIPacker>(builder: inout FlatBufferBuilder, type: T.Type) -> ByteBuffer where T.T == Self {
+ public func serialize<T: ObjectAPIPacker>(
+ builder: inout FlatBufferBuilder,
+ type: T.Type) -> ByteBuffer where T.T == Self
+ {
var s = self
let root = type.pack(&builder, obj: &s)
builder.finish(offset: root)
diff --git a/swift/Sources/FlatBuffers/Root.swift b/swift/Sources/FlatBuffers/Root.swift
new file mode 100644
index 00000000..8891cafb
--- /dev/null
+++ b/swift/Sources/FlatBuffers/Root.swift
@@ -0,0 +1,68 @@
+/*
+ * 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
+
+/// Takes in a prefixed sized buffer, where the prefixed size would be skipped.
+/// And would verify that the buffer passed is a valid `Flatbuffers` Object.
+/// - Parameters:
+/// - byteBuffer: Buffer that needs to be checked and read
+/// - options: Verifier options
+/// - Throws: FlatbuffersErrors
+/// - Returns: Returns a valid, checked Flatbuffers object
+public func getPrefixedSizeCheckedRoot<T: FlatBufferObject & Verifiable>(
+ byteBuffer: inout ByteBuffer,
+ options: VerifierOptions = .init()) throws -> T
+{
+ byteBuffer.skipPrefix()
+ return try getCheckedRoot(byteBuffer: &byteBuffer, options: options)
+}
+
+/// Takes in a prefixed sized buffer, where the prefixed size would be skipped.
+/// Returns a `NON-Checked` flatbuffers object
+/// - Parameter byteBuffer: Buffer that contains data
+/// - Returns: Returns a Flatbuffers object
+public func getPrefixedSizeRoot<T: FlatBufferObject>(byteBuffer: inout ByteBuffer) -> T {
+ byteBuffer.skipPrefix()
+ return getRoot(byteBuffer: &byteBuffer)
+
+}
+
+/// Verifies that the buffer passed is a valid `Flatbuffers` Object.
+/// - Parameters:
+/// - byteBuffer: Buffer that needs to be checked and read
+/// - options: Verifier options
+/// - Throws: FlatbuffersErrors
+/// - Returns: Returns a valid, checked Flatbuffers object
+public func getCheckedRoot<T: FlatBufferObject & Verifiable>(
+ byteBuffer: inout ByteBuffer,
+ options: VerifierOptions = .init()) throws -> T
+{
+ var verifier = try Verifier(buffer: &byteBuffer, options: options)
+ try ForwardOffset<T>.verify(&verifier, at: 0, of: T.self)
+ return T.init(
+ byteBuffer,
+ o: Int32(byteBuffer.read(def: UOffset.self, position: byteBuffer.reader)) + Int32(byteBuffer.reader))
+}
+
+/// Returns a `NON-Checked` flatbuffers object
+/// - Parameter byteBuffer: Buffer that contains data
+/// - Returns: Returns a Flatbuffers object
+public func getRoot<T: FlatBufferObject>(byteBuffer: inout ByteBuffer) -> T {
+ T.init(
+ byteBuffer,
+ o: Int32(byteBuffer.read(def: UOffset.self, position: byteBuffer.reader)) + Int32(byteBuffer.reader))
+}
diff --git a/swift/Sources/FlatBuffers/String+extension.swift b/swift/Sources/FlatBuffers/String+extension.swift
index 7c9b06e7..5a16a81b 100644
--- a/swift/Sources/FlatBuffers/String+extension.swift
+++ b/swift/Sources/FlatBuffers/String+extension.swift
@@ -16,6 +16,42 @@
import Foundation
+extension String: Verifiable {
+
+ /// Verifies that the current value is which the bounds of the buffer, and if
+ /// the current `Value` is aligned properly
+ /// - Parameters:
+ /// - verifier: Verifier that hosts the buffer
+ /// - position: Current position within the buffer
+ /// - type: The type of the object to be verified
+ /// - Throws: Errors coming from `inBuffer`, `missingNullTerminator` and `outOfBounds`
+ public static func verify<T>(
+ _ verifier: inout Verifier,
+ at position: Int,
+ of type: T.Type) throws where T: Verifiable
+ {
+
+ let range = try String.verifyRange(&verifier, at: position, of: UInt8.self)
+ /// Safe &+ since we already check for overflow in verify range
+ let stringLen = range.start &+ range.count
+
+ if stringLen >= verifier.capacity {
+ throw FlatbuffersErrors.outOfBounds(
+ position: UInt(clamping: stringLen.magnitude),
+ end: verifier.capacity)
+ }
+
+ let isNullTerminated = verifier._buffer.read(
+ def: UInt8.self,
+ position: stringLen) == 0
+
+ if !verifier._options._ignoreMissingNullTerminators && !isNullTerminated {
+ let str = verifier._buffer.readString(at: range.start, count: range.count)
+ throw FlatbuffersErrors.missingNullTerminator(position: position, str: str)
+ }
+ }
+}
+
extension String: FlatbuffersInitializable {
/// Initailizes a string from a Flatbuffers ByteBuffer
@@ -23,10 +59,11 @@ extension String: FlatbuffersInitializable {
/// - bb: ByteBuffer containing the readable string
/// - o: Current position
public init(_ bb: ByteBuffer, o: Int32) {
- let count = bb.read(def: Int32.self, position: Int(o))
+ let v = Int(o)
+ let count = bb.read(def: Int32.self, position: v)
self = bb.readString(
- at: Int32(MemoryLayout<Int32>.size) + o,
- count: count) ?? ""
+ at: MemoryLayout<Int32>.size + v,
+ count: Int(count)) ?? ""
}
}
@@ -53,7 +90,10 @@ extension String: NativeObject {
fatalError("serialize should never be called from string directly")
}
- public func serialize<T: ObjectAPIPacker>(builder: inout FlatBufferBuilder, type: T.Type) -> ByteBuffer where T.T == Self {
+ public func serialize<T: ObjectAPIPacker>(
+ builder: inout FlatBufferBuilder,
+ type: T.Type) -> ByteBuffer where T.T == Self
+ {
fatalError("serialize should never be called from string directly")
}
}
diff --git a/swift/Sources/FlatBuffers/Struct.swift b/swift/Sources/FlatBuffers/Struct.swift
index 0b546d9d..ac701d46 100644
--- a/swift/Sources/FlatBuffers/Struct.swift
+++ b/swift/Sources/FlatBuffers/Struct.swift
@@ -16,16 +16,30 @@
import Foundation
+/// Struct is a representation of a mutable `Flatbuffers` struct
+/// since native structs are value types and cant be mutated
@frozen
public struct Struct {
+
+ /// Hosting Bytebuffer
public private(set) var bb: ByteBuffer
+ /// Current position of the struct
public private(set) var postion: Int32
+ /// Initializer for a mutable flatbuffers struct
+ /// - Parameters:
+ /// - bb: Current hosting Bytebuffer
+ /// - position: Current position for the struct in the ByteBuffer
public init(bb: ByteBuffer, position: Int32 = 0) {
self.bb = bb
postion = position
}
+ /// Reads data from the buffer directly at offset O
+ /// - Parameters:
+ /// - type: Type of data to be read
+ /// - o: Current offset of the data
+ /// - Returns: Data of Type T that conforms to type Scalar
public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
let r = bb.read(def: T.self, position: Int(o + postion))
return r
diff --git a/swift/Sources/FlatBuffers/Table.swift b/swift/Sources/FlatBuffers/Table.swift
index 7c185559..34efedd5 100644
--- a/swift/Sources/FlatBuffers/Table.swift
+++ b/swift/Sources/FlatBuffers/Table.swift
@@ -16,11 +16,22 @@
import Foundation
+/// `Table` is a Flatbuffers object that can read,
+/// mutate scalar fields within a valid flatbuffers buffer
@frozen
public struct Table {
+
+ /// Hosting Bytebuffer
public private(set) var bb: ByteBuffer
+ /// Current position of the table within the buffer
public private(set) var postion: Int32
+ /// Initializer for the table interface to allow generated code to read
+ /// data from memory
+ /// - Parameters:
+ /// - bb: ByteBuffer that stores data
+ /// - position: Current table position
+ /// - Note: This will `CRASH` if read on a big endian machine
public init(bb: ByteBuffer, position: Int32 = 0) {
guard isLitteEndian else {
fatalError("Reading/Writing a buffer in big endian machine is not supported on swift")
@@ -29,6 +40,10 @@ public struct Table {
postion = position
}
+ /// Gets the offset of the current field within the buffer by reading
+ /// the vtable
+ /// - Parameter o: current offset
+ /// - Returns: offset of field within buffer
public func offset(_ o: Int32) -> Int32 {
let vtable = postion - bb.read(def: Int32.self, position: Int(postion))
return o < bb.read(def: VOffset.self, position: Int(vtable)) ? Int32(bb.read(
@@ -36,7 +51,13 @@ public struct Table {
position: Int(vtable + o))) : 0
}
- public func indirect(_ o: Int32) -> Int32 { o + bb.read(def: Int32.self, position: Int(o)) }
+ /// Gets the indirect offset of the current stored object
+ /// (applicable only for object arrays)
+ /// - Parameter o: current offset
+ /// - Returns: offset of field within buffer
+ public func indirect(_ o: Int32) -> Int32 {
+ o + bb.read(def: Int32.self, position: Int(o))
+ }
/// String reads from the buffer with respect to position of the current table.
/// - Parameter offset: Offset of the string
@@ -45,14 +66,15 @@ public struct Table {
}
/// Direct string reads from the buffer disregarding the position of the table.
- /// It would be preferable to use string unless the current position of the table is not needed
+ /// It would be preferable to use string unless the current position of the table
+ /// is not needed
/// - Parameter offset: Offset of the string
public func directString(at offset: Int32) -> String? {
var offset = offset
offset += bb.read(def: Int32.self, position: Int(offset))
let count = bb.read(def: Int32.self, position: Int(offset))
- let position = offset + Int32(MemoryLayout<Int32>.size)
- return bb.readString(at: position, count: count)
+ let position = Int(offset) + MemoryLayout<Int32>.size
+ return bb.readString(at: position, count: Int(count))
}
/// Reads from the buffer with respect to the position in the table.
@@ -81,19 +103,30 @@ public struct Table {
return r
}
+ /// Returns that current `Union` object at a specific offset
+ /// by adding offset to the current position of table
+ /// - Parameter o: offset
+ /// - Returns: A flatbuffers object
public func union<T: FlatbuffersInitializable>(_ o: Int32) -> T {
let o = o + postion
return directUnion(o)
}
+ /// Returns a direct `Union` object at a specific offset
+ /// - Parameter o: offset
+ /// - Returns: A flatbuffers object
public func directUnion<T: FlatbuffersInitializable>(_ o: Int32) -> T {
T.init(bb, o: o + bb.read(def: Int32.self, position: Int(o)))
}
+ /// Returns a vector of type T at a specific offset
+ /// This should only be used by `Scalars`
+ /// - Parameter off: Readable offset
+ /// - Returns: Returns a vector of type [T]
public func getVector<T>(at off: Int32) -> [T]? {
let o = offset(off)
guard o != 0 else { return nil }
- return bb.readSlice(index: vector(at: o), count: vector(count: o))
+ return bb.readSlice(index: Int(vector(at: o)), count: Int(vector(count: o)))
}
/// Vector count gets the count of Elements within the array
@@ -115,17 +148,36 @@ public struct Table {
return o + bb.read(def: Int32.self, position: Int(o)) + 4
}
- static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 { o + fbb.read(
- def: Int32.self,
- position: Int(o)) }
+ /// Reading an indirect offset of a table.
+ /// - Parameters:
+ /// - o: position within the buffer
+ /// - fbb: ByteBuffer
+ /// - Returns: table offset
+ static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 {
+ o + fbb.read(def: Int32.self, position: Int(o))
+ }
+ /// Gets a vtable value according to an table Offset and a field offset
+ /// - Parameters:
+ /// - o: offset relative to entire buffer
+ /// - vOffset: Field offset within a vtable
+ /// - fbb: ByteBuffer
+ /// - Returns: an position of a field
static public func offset(_ o: Int32, vOffset: Int32, fbb: ByteBuffer) -> Int32 {
let vTable = Int32(fbb.capacity) - o
return vTable + Int32(fbb.read(
def: Int16.self,
- position: Int(vTable + vOffset - fbb.read(def: Int32.self, position: Int(vTable)))))
+ position: Int(vTable + vOffset - fbb.read(
+ def: Int32.self,
+ position: Int(vTable)))))
}
+ /// Compares two objects at offset A and offset B within a ByteBuffer
+ /// - Parameters:
+ /// - off1: first offset to compare
+ /// - off2: second offset to compare
+ /// - fbb: Bytebuffer
+ /// - Returns: returns the difference between
static public func compare(_ off1: Int32, _ off2: Int32, fbb: ByteBuffer) -> Int32 {
let memorySize = Int32(MemoryLayout<Int32>.size)
let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
@@ -145,6 +197,12 @@ public struct Table {
return len1 - len2
}
+ /// Compares two objects at offset A and array of `Bytes` within a ByteBuffer
+ /// - Parameters:
+ /// - off1: Offset to compare to
+ /// - key: bytes array to compare to
+ /// - fbb: Bytebuffer
+ /// - Returns: returns the difference between
static public func compare(_ off1: Int32, _ key: [Byte], fbb: ByteBuffer) -> Int32 {
let memorySize = Int32(MemoryLayout<Int32>.size)
let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
diff --git a/swift/Sources/FlatBuffers/TableVerifier.swift b/swift/Sources/FlatBuffers/TableVerifier.swift
new file mode 100644
index 00000000..6749b6f0
--- /dev/null
+++ b/swift/Sources/FlatBuffers/TableVerifier.swift
@@ -0,0 +1,202 @@
+/*
+ * 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
+
+/// `TableVerifier` verifies a table object is within a provided memory.
+/// It checks if all the objects for a specific generated table, are within
+/// the bounds of the buffer, aligned.
+public struct TableVerifier {
+
+ /// position of current table in `ByteBuffer`
+ fileprivate var _position: Int
+
+ /// Current VTable position
+ fileprivate var _vtable: Int
+
+ /// Length of current VTable
+ fileprivate var _vtableLength: Int
+
+ /// `Verifier` object created in the base verifable call.
+ fileprivate var _verifier: Verifier
+
+ /// Creates a `TableVerifier` verifier that allows the Flatbuffer object
+ /// to verify the buffer before accessing any of the data.
+ ///
+ /// - Parameters:
+ /// - position: Current table Position
+ /// - vtable: Current `VTable` position
+ /// - vtableLength: Current `VTable` length
+ /// - verifier: `Verifier` Object that caches the data of the verifiable object
+ internal init(
+ position: Int,
+ vtable: Int,
+ vtableLength: Int,
+ verifier: inout Verifier)
+ {
+ _position = position
+ _vtable = vtable
+ _vtableLength = vtableLength
+ _verifier = verifier
+ }
+
+ /// Dereference the current object position from the `VTable`
+ /// - Parameter field: Current VTable refrence to position.
+ /// - Throws: A `FlatbuffersErrors` incase the voffset is not aligned/outOfBounds/apparentSizeTooLarge
+ /// - Returns: An optional position for current field
+ internal mutating func dereference(_ field: VOffset) throws -> Int? {
+ if field >= _vtableLength {
+ return nil
+ }
+
+ /// Reading the offset for the field needs to be read.
+ let offset: VOffset = try _verifier.getValue(
+ at: Int(clamping: _vtable &+ Int(field))
+ )
+
+ if offset > 0 {
+ return Int(clamping: _position &+ Int(offset))
+ }
+ return nil
+ }
+
+ /// Visits all the fields within the table to validate the integrity
+ /// of the data
+ /// - Parameters:
+ /// - field: voffset of the current field to be read
+ /// - fieldName: fieldname to report data Errors.
+ /// - required: If the field has to be available in the buffer
+ /// - type: Type of field to be read
+ /// - Throws: A `FlatbuffersErrors` where the field is corrupt
+ public mutating func visit<T>(
+ field: VOffset,
+ fieldName: String,
+ required: Bool,
+ type: T.Type) throws where T: Verifiable
+ {
+ let derefValue = try dereference(field)
+
+ if let value = derefValue {
+ try T.verify(&_verifier, at: value, of: T.self)
+ return
+ }
+ if required {
+ throw FlatbuffersErrors.requiredFieldDoesntExist(
+ position: field,
+ name: fieldName)
+ }
+ }
+
+ /// Visits all the fields for a union object within the table to
+ /// validate the integrity of the data
+ /// - Parameters:
+ /// - key: Current Key Voffset
+ /// - field: Current field Voffset
+ /// - unionKeyName: Union key name
+ /// - fieldName: Field key name
+ /// - required: indicates if an object is required to be present
+ /// - completion: Completion is a handler that WILL be called in the generated
+ /// - Throws: A `FlatbuffersErrors` where the field is corrupt
+ public mutating func visit<T>(
+ unionKey key: VOffset,
+ unionField field: VOffset,
+ unionKeyName: String,
+ fieldName: String,
+ required: Bool,
+ completion: @escaping (inout Verifier, T, Int) throws -> Void) throws where T: UnionEnum
+ {
+ let keyPos = try dereference(key)
+ let valPos = try dereference(field)
+
+ if keyPos == nil && valPos == nil {
+ if required {
+ throw FlatbuffersErrors.requiredFieldDoesntExist(
+ position: key,
+ name: unionKeyName)
+ }
+ return
+ }
+
+ if let _key = keyPos,
+ let _val = valPos
+ {
+ /// verifiying that the key is within the buffer
+ try T.T.verify(&_verifier, at: _key, of: T.T.self)
+ guard let _enum = try T.init(value: _verifier._buffer.read(
+ def: T.T.self,
+ position: _key)) else
+ {
+ throw FlatbuffersErrors.unknownUnionCase
+ }
+ /// we are assuming that Unions will always be of type Uint8
+ try completion(
+ &_verifier,
+ _enum,
+ _val)
+ return
+ }
+ throw FlatbuffersErrors.valueNotFound(
+ key: keyPos,
+ keyName: unionKeyName,
+ field: valPos,
+ fieldName: fieldName)
+ }
+
+ /// Visits and validates all the objects within a union vector
+ /// - Parameters:
+ /// - key: Current Key Voffset
+ /// - field: Current field Voffset
+ /// - unionKeyName: Union key name
+ /// - fieldName: Field key name
+ /// - required: indicates if an object is required to be present
+ /// - completion: Completion is a handler that WILL be called in the generated
+ /// - Throws: A `FlatbuffersErrors` where the field is corrupt
+ public mutating func visitUnionVector<T>(
+ unionKey key: VOffset,
+ unionField field: VOffset,
+ unionKeyName: String,
+ fieldName: String,
+ required: Bool,
+ completion: @escaping (inout Verifier, T, Int) throws -> Void) throws where T: UnionEnum
+ {
+ let keyVectorPosition = try dereference(key)
+ let offsetVectorPosition = try dereference(field)
+
+ if let keyPos = keyVectorPosition,
+ let valPos = offsetVectorPosition
+ {
+ try UnionVector<T>.verify(
+ &_verifier,
+ keyPosition: keyPos,
+ fieldPosition: valPos,
+ unionKeyName: unionKeyName,
+ fieldName: fieldName,
+ completion: completion)
+ return
+ }
+ if required {
+ throw FlatbuffersErrors.requiredFieldDoesntExist(
+ position: field,
+ name: fieldName)
+ }
+ }
+
+ /// Finishs the current Table verifier, and subtracts the current
+ /// table from the incremented depth.
+ public mutating func finish() {
+ _verifier.finish()
+ }
+}
diff --git a/swift/Sources/FlatBuffers/VeriferOptions.swift b/swift/Sources/FlatBuffers/VeriferOptions.swift
new file mode 100644
index 00000000..454dd51e
--- /dev/null
+++ b/swift/Sources/FlatBuffers/VeriferOptions.swift
@@ -0,0 +1,52 @@
+/*
+ * 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
+
+/// `VerifierOptions` is a set of options to verify a flatbuffer
+public struct VerifierOptions {
+
+ /// Maximum `Apparent` size if the buffer can be expanded into a DAG tree
+ internal var _maxApparentSize: UOffset
+
+ /// Maximum table count allowed in a buffer
+ internal var _maxTableCount: UOffset
+
+ /// Maximum depth allowed in a buffer
+ internal var _maxDepth: UOffset
+
+ /// Ignoring missing null terminals in strings
+ internal var _ignoreMissingNullTerminators: Bool
+
+ /// initializes the set of options for the verifier
+ /// - Parameters:
+ /// - maxDepth: Maximum depth allowed in a buffer
+ /// - maxTableCount: Maximum table count allowed in a buffer
+ /// - maxApparentSize: Maximum `Apparent` size if the buffer can be expanded into a DAG tree
+ /// - ignoreMissingNullTerminators: Ignoring missing null terminals in strings *Currently not supported in swift*
+ public init(
+ maxDepth: UOffset = 64,
+ maxTableCount: UOffset = 1000000,
+ maxApparentSize: UOffset = 1 << 31,
+ ignoreMissingNullTerminators: Bool = false)
+ {
+ _maxDepth = maxDepth
+ _maxTableCount = maxTableCount
+ _maxApparentSize = maxApparentSize
+ _ignoreMissingNullTerminators = ignoreMissingNullTerminators
+ }
+
+}
diff --git a/swift/Sources/FlatBuffers/Verifiable.swift b/swift/Sources/FlatBuffers/Verifiable.swift
new file mode 100644
index 00000000..e601cfc2
--- /dev/null
+++ b/swift/Sources/FlatBuffers/Verifiable.swift
@@ -0,0 +1,211 @@
+/*
+ * 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
+
+/// Verifiable is a protocol all swift flatbuffers object should conform to,
+/// since swift is similar to `cpp` and `rust` where the data is read directly
+/// from `unsafeMemory` thus the need to verify if the buffer received is a valid one
+public protocol Verifiable {
+
+ /// Verifies that the current value is which the bounds of the buffer, and if
+ /// the current `Value` is aligned properly
+ /// - Parameters:
+ /// - verifier: Verifier that hosts the buffer
+ /// - position: Current position within the buffer
+ /// - type: The type of the object to be verified
+ /// - Throws: Errors coming from `inBuffer` function
+ static func verify<T>(
+ _ verifier: inout Verifier,
+ at position: Int,
+ of type: T.Type) throws where T: Verifiable
+}
+
+extension Verifiable {
+
+ /// Verifies if the current range to be read is within the bounds of the buffer,
+ /// and if the range is properly aligned
+ /// - Parameters:
+ /// - verifier: Verifier that hosts the buffer
+ /// - position: Current position within the buffer
+ /// - type: The type of the object to be verified
+ /// - Throws: Erros thrown from `isAligned` & `rangeInBuffer`
+ /// - Returns: a tuple of the start position and the count of objects within the range
+ @discardableResult
+ public static func verifyRange<T>(
+ _ verifier: inout Verifier,
+ at position: Int, of type: T.Type) throws -> (start: Int, count: Int)
+ {
+ let len: UOffset = try verifier.getValue(at: position)
+ let intLen = Int(len)
+ let start = Int(clamping: (position &+ MemoryLayout<Int32>.size).magnitude)
+ try verifier.isAligned(position: start, type: type.self)
+ try verifier.rangeInBuffer(position: start, size: intLen)
+ return (start, intLen)
+ }
+}
+
+extension Verifiable where Self: Scalar {
+
+ /// Verifies that the current value is which the bounds of the buffer, and if
+ /// the current `Value` is aligned properly
+ /// - Parameters:
+ /// - verifier: Verifier that hosts the buffer
+ /// - position: Current position within the buffer
+ /// - type: The type of the object to be verified
+ /// - Throws: Errors coming from `inBuffer` function
+ public static func verify<T>(
+ _ verifier: inout Verifier,
+ at position: Int,
+ of type: T.Type) throws where T: Verifiable
+ {
+ try verifier.inBuffer(position: position, of: type.self)
+ }
+}
+
+// MARK: - ForwardOffset
+
+/// ForwardOffset is a container to wrap around the Generic type to be verified
+/// from the flatbuffers object.
+public enum ForwardOffset<U>: Verifiable where U: Verifiable {
+
+ /// Verifies that the current value is which the bounds of the buffer, and if
+ /// the current `Value` is aligned properly
+ /// - Parameters:
+ /// - verifier: Verifier that hosts the buffer
+ /// - position: Current position within the buffer
+ /// - type: The type of the object to be verified
+ /// - Throws: Errors coming from `inBuffer` function
+ public static func verify<T>(
+ _ verifier: inout Verifier,
+ at position: Int,
+ of type: T.Type) throws where T: Verifiable
+ {
+ let offset: UOffset = try verifier.getValue(at: position)
+ let nextOffset = Int(clamping: (Int(offset) &+ position).magnitude)
+ try U.verify(&verifier, at: nextOffset, of: U.self)
+ }
+}
+
+// MARK: - Vector
+
+/// Vector is a container to wrap around the Generic type to be verified
+/// from the flatbuffers object.
+public enum Vector<U, S>: Verifiable where U: Verifiable, S: Verifiable {
+
+ /// Verifies that the current value is which the bounds of the buffer, and if
+ /// the current `Value` is aligned properly
+ /// - Parameters:
+ /// - verifier: Verifier that hosts the buffer
+ /// - position: Current position within the buffer
+ /// - type: The type of the object to be verified
+ /// - Throws: Errors coming from `inBuffer` function
+ public static func verify<T>(
+ _ verifier: inout Verifier,
+ at position: Int,
+ of type: T.Type) throws where T: Verifiable
+ {
+ /// checks if the next verification type S is equal to U of type forwardOffset
+ /// This had to be done since I couldnt find a solution for duplicate call functions
+ /// A fix will be appreciated
+ if U.self is ForwardOffset<S>.Type {
+ let range = try verifyRange(&verifier, at: position, of: UOffset.self)
+ for index in stride(
+ from: range.start,
+ to: Int(clamping: range.start &+ range.count),
+ by: MemoryLayout<UOffset>.size)
+ {
+ try U.verify(&verifier, at: index, of: U.self)
+ }
+ } else {
+ try S.verifyRange(&verifier, at: position, of: S.self)
+ }
+ }
+}
+
+// MARK: - UnionVector
+
+/// UnionVector is a container to wrap around the Generic type to be verified
+/// from the flatbuffers object.
+public enum UnionVector<S> where S: UnionEnum {
+
+ /// Completion handler for the function Verify, that passes the verifier
+ /// enum type and position of union field
+ public typealias Completion = (inout Verifier, S, Int) throws -> Void
+
+ /// Verifies if the current range to be read is within the bounds of the buffer,
+ /// and if the range is properly aligned. It also verifies if the union type is a
+ /// *valid/supported* union type.
+ /// - Parameters:
+ /// - verifier: Verifier that hosts the buffer
+ /// - keyPosition: Current union key position within the buffer
+ /// - fieldPosition: Current union field position within the buffer
+ /// - unionKeyName: Name of key to written if error is presented
+ /// - fieldName: Name of field to written if error is presented
+ /// - completion: Completion is a handler that WILL be called in the generated
+ /// code to verify the actual objects
+ /// - Throws: FlatbuffersErrors
+ public static func verify(
+ _ verifier: inout Verifier,
+ keyPosition: Int,
+ fieldPosition: Int,
+ unionKeyName: String,
+ fieldName: String,
+ completion: @escaping Completion) throws
+ {
+ /// Get offset for union key vectors and offset vectors
+ let keyOffset: UOffset = try verifier.getValue(at: keyPosition)
+ let fieldOffset: UOffset = try verifier.getValue(at: fieldPosition)
+
+ /// Check if values are within the buffer, returns the start position of vectors, and vector counts
+ /// Using &+ is safe since we already verified that the value is within the buffer, where the max is
+ /// going to be 2Gib and swift supports Int64 by default
+ let keysRange = try S.T.verifyRange(
+ &verifier,
+ at: Int(keyOffset) &+ keyPosition,
+ of: S.T.self)
+ let offsetsRange = try UOffset.verifyRange(
+ &verifier,
+ at: Int(fieldOffset) &+ fieldPosition,
+ of: UOffset.self)
+
+ guard keysRange.count == offsetsRange.count else {
+ throw FlatbuffersErrors.unionVectorSize(
+ keyVectorSize: keysRange.count,
+ fieldVectorSize: offsetsRange.count,
+ unionKeyName: unionKeyName,
+ fieldName: fieldName)
+ }
+
+ var count = 0
+ /// Iterate over the vector of keys and offsets.
+ while count < keysRange.count {
+
+ /// index of readable enum value in array
+ let keysIndex = MemoryLayout<S.T>.size * count
+ guard let _enum = try S.init(value: verifier._buffer.read(
+ def: S.T.self,
+ position: keysRange.start + keysIndex)) else
+ {
+ throw FlatbuffersErrors.unknownUnionCase
+ }
+ /// index of readable offset value in array
+ let fieldIndex = MemoryLayout<UOffset>.size * count
+ try completion(&verifier, _enum, offsetsRange.start + fieldIndex)
+ count += 1
+ }
+ }
+}
diff --git a/swift/Sources/FlatBuffers/Verifier.swift b/swift/Sources/FlatBuffers/Verifier.swift
new file mode 100644
index 00000000..e465b140
--- /dev/null
+++ b/swift/Sources/FlatBuffers/Verifier.swift
@@ -0,0 +1,199 @@
+/*
+ * 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
+
+/// Verifier that check if the buffer passed into it is a valid,
+/// safe, aligned Flatbuffers object since swift read from `unsafeMemory`
+public struct Verifier {
+
+ /// Flag to check for alignment if true
+ fileprivate let _checkAlignment: Bool
+ /// Capacity of the current buffer
+ fileprivate var _capacity: Int
+ /// Current ApparentSize
+ fileprivate var _apparentSize: UOffset = 0
+ /// Amount of tables present within a buffer
+ fileprivate var _tableCount = 0
+
+ /// Capacity of the buffer
+ internal var capacity: Int { _capacity }
+ /// Current reached depth within the buffer
+ internal var _depth = 0
+ /// Current verifiable ByteBuffer
+ internal var _buffer: ByteBuffer
+ /// Options for verification
+ internal let _options: VerifierOptions
+
+ /// Initializer for the verifier
+ /// - Parameters:
+ /// - buffer: Bytebuffer that is required to be verified
+ /// - options: `VerifierOptions` that set the rule for some of the verification done
+ /// - checkAlignment: If alignment check is required to be preformed
+ /// - Throws: `exceedsMaxSizeAllowed` if capacity of the buffer is more than 2GiB
+ public init(
+ buffer: inout ByteBuffer,
+ options: VerifierOptions = .init(),
+ checkAlignment: Bool = true) throws
+ {
+ guard buffer.capacity < FlatBufferMaxSize else {
+ throw FlatbuffersErrors.exceedsMaxSizeAllowed
+ }
+
+ _buffer = buffer
+ _capacity = buffer.capacity
+ _checkAlignment = checkAlignment
+ _options = options
+ }
+
+ /// Resets the verifier to initial state
+ public mutating func reset() {
+ _depth = 0
+ _tableCount = 0
+ }
+
+ /// Checks if the value of type `T` is aligned properly in the buffer
+ /// - Parameters:
+ /// - position: Current position
+ /// - type: Type of value to check
+ /// - Throws: `missAlignedPointer` if the pointer is not aligned properly
+ public mutating func isAligned<T>(position: Int, type: T.Type) throws {
+
+ /// If check alignment is false this mutating function doesnt continue
+ if !_checkAlignment { return }
+
+ /// advance pointer to position X
+ let ptr = _buffer._storage.memory.advanced(by: position)
+ /// Check if the pointer is aligned
+ if Int(bitPattern: ptr) & (MemoryLayout<T>.alignment &- 1) == 0 {
+ return
+ }
+
+ throw FlatbuffersErrors.missAlignedPointer(
+ position: position,
+ type: String(describing: T.self))
+ }
+
+ /// Checks if the value of Size "X" is within the range of the buffer
+ /// - Parameters:
+ /// - position: Current postion to be read
+ /// - size: `Byte` Size of readable object within the buffer
+ /// - Throws: `outOfBounds` if the value is out of the bounds of the buffer
+ /// and `apparentSizeTooLarge` if the apparent size is bigger than the one specified
+ /// in `VerifierOptions`
+ public mutating func rangeInBuffer(position: Int, size: Int) throws {
+ let end = UInt(clamping: (position &+ size).magnitude)
+ if end > _buffer.capacity {
+ throw FlatbuffersErrors.outOfBounds(position: end, end: capacity)
+ }
+ _apparentSize = _apparentSize &+ UInt32(size)
+ if _apparentSize > _options._maxApparentSize {
+ throw FlatbuffersErrors.apparentSizeTooLarge
+ }
+ }
+
+ /// Validates if a value of type `T` is aligned and within the bounds of
+ /// the buffer
+ /// - Parameters:
+ /// - position: Current readable position
+ /// - type: Type of value to check
+ /// - Throws: FlatbuffersErrors
+ public mutating func inBuffer<T>(position: Int, of type: T.Type) throws {
+ try isAligned(position: position, type: type)
+ try rangeInBuffer(position: position, size: MemoryLayout<T>.size)
+ }
+
+ /// Visits a table at the current position and validates if the table meets
+ /// the rules specified in the `VerifierOptions`
+ /// - Parameter position: Current position to be read
+ /// - Throws: FlatbuffersErrors
+ /// - Returns: A `TableVerifier` at the current readable table
+ public mutating func visitTable(at position: Int) throws -> TableVerifier {
+ let vtablePosition = try derefOffset(position: position)
+ let vtableLength: VOffset = try getValue(at: vtablePosition)
+
+ let length = Int(vtableLength)
+ try isAligned(
+ position: Int(clamping: (vtablePosition + length).magnitude),
+ type: VOffset.self)
+ try rangeInBuffer(position: vtablePosition, size: length)
+
+ _tableCount += 1
+
+ if _tableCount > _options._maxTableCount {
+ throw FlatbuffersErrors.maximumTables
+ }
+
+ _depth += 1
+
+ if _depth > _options._maxDepth {
+ throw FlatbuffersErrors.maximumDepth
+ }
+
+ return TableVerifier(
+ position: position,
+ vtable: vtablePosition,
+ vtableLength: length,
+ verifier: &self)
+ }
+
+ /// Validates if a value of type `T` is within the buffer and returns it
+ /// - Parameter position: Current position to be read
+ /// - Throws: `inBuffer` errors
+ /// - Returns: a value of type `T` usually a `VTable` or a table offset
+ internal mutating func getValue<T>(at position: Int) throws -> T {
+ try inBuffer(position: position, of: T.self)
+ return _buffer.read(def: T.self, position: position)
+ }
+
+ /// derefrences an offset within a vtable to get the position of the field
+ /// in the bytebuffer
+ /// - Parameter position: Current readable position
+ /// - Throws: `inBuffer` errors & `signedOffsetOutOfBounds`
+ /// - Returns: Current readable position for a field
+ @inline(__always)
+ internal mutating func derefOffset(position: Int) throws -> Int {
+ try inBuffer(position: position, of: Int32.self)
+
+ let offset = _buffer.read(def: Int32.self, position: position)
+ // switching to int32 since swift's default Int is int64
+ // this should be safe since we already checked if its within
+ // the buffer
+ let _int32Position = UInt32(position)
+
+ let reportedOverflow: (partialValue: UInt32, overflow: Bool)
+ if offset > 0 {
+ reportedOverflow = _int32Position.subtractingReportingOverflow(offset.magnitude)
+ } else {
+ reportedOverflow = _int32Position.addingReportingOverflow(offset.magnitude)
+ }
+
+ /// since `subtractingReportingOverflow` & `addingReportingOverflow` returns true,
+ /// if there is overflow we return failure
+ if reportedOverflow.overflow || reportedOverflow.partialValue > _buffer.capacity {
+ throw FlatbuffersErrors.signedOffsetOutOfBounds(
+ offset: Int(offset),
+ position: position)
+ }
+
+ return Int(reportedOverflow.partialValue)
+ }
+
+ /// finishes the current iteration of verification on an object
+ internal mutating func finish() {
+ _depth -= 1
+ }
+}
diff --git a/tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift b/tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift
index 114e8f70..da9a3d9b 100644
--- a/tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift
+++ b/tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift
@@ -40,7 +40,7 @@ func run(name: String, runs: Int, action: () -> Void) -> Benchmark {
func createDocument(Benchmarks: [Benchmark]) -> String {
let separator = "-------------------------------------"
var document = "\(separator)\n"
- document += "\(String(format: "|\t%@\t\t|\t\t%@\t\t|", "Name", "Scores"))\n"
+ document += "\(String(format: "|\t%@\t\t |\t\t%@\t\t|", "Name", "Scores"))\n"
document += "\(separator)\n"
for i in Benchmarks {
document += "\(i.description) \n"
@@ -89,7 +89,9 @@ func benchmarkThreeMillionStructs() {
var offsets: [Offset] = []
for _ in 0..<structCount {
- fb.startVector(5 * MemoryLayout<AA>.size, elementSize: MemoryLayout<AA>.alignment)
+ fb.startVector(
+ 5 * MemoryLayout<AA>.size,
+ elementSize: MemoryLayout<AA>.alignment)
for _ in 0..<5 {
_ = fb.create(struct: AA(a: 2.4, b: 2.4))
}
@@ -119,12 +121,18 @@ struct AA: NativeStruct {
func benchmark(numberOfRuns runs: Int) {
var benchmarks: [Benchmark] = []
let str = (0...99).map { _ -> String in "x" }.joined()
- benchmarks.append(run(name: "500_000", runs: runs, action: benchmarkFiveHundredAdds))
+ benchmarks.append(run(
+ name: "500_000",
+ runs: runs,
+ action: benchmarkFiveHundredAdds))
benchmarks.append(run(name: "10 str", runs: runs, action: create10Strings))
let hundredStr = run(name: "100 str", runs: runs) {
create100Strings(str: str)
}
- benchmarks.append(run(name: "3M strc", runs: 1, action: benchmarkThreeMillionStructs))
+ benchmarks.append(run(
+ name: "3M strc",
+ runs: 1,
+ action: benchmarkThreeMillionStructs))
benchmarks.append(hundredStr)
print(createDocument(Benchmarks: benchmarks))
}
diff --git a/tests/FlatBuffers.Test.Swift/Package.swift b/tests/FlatBuffers.Test.Swift/Package.swift
index ec36de32..12618cbe 100644
--- a/tests/FlatBuffers.Test.Swift/Package.swift
+++ b/tests/FlatBuffers.Test.Swift/Package.swift
@@ -28,7 +28,9 @@ let package = Package(
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0"),
],
targets: [
- .target(name: "SwiftFlatBuffers"),
+ .target(
+ name: "SwiftFlatBuffers",
+ dependencies: ["FlatBuffers"]),
.testTarget(
name: "FlatBuffers.Test.SwiftTests",
dependencies: ["FlatBuffers", "GRPC"]),
diff --git a/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/fuzzer.fbs b/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/fuzzer.fbs
new file mode 100644
index 00000000..e0356fa3
--- /dev/null
+++ b/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/fuzzer.fbs
@@ -0,0 +1,32 @@
+enum Color:ubyte (bit_flags) {
+ Red = 0, // color Red = (1u << 0)
+ /// \brief color Green
+ /// Green is bit_flag with value (1u << 1)
+ Green,
+ /// \brief color Blue (1u << 3)
+ Blue = 3,
+}
+
+struct Test { a:short; b:byte; }
+
+struct Vec3 (force_align: 8) {
+ x:float;
+ y:float;
+ z:float;
+ test1:double;
+ test2:Color;
+ test3:Test;
+}
+
+/// an example documentation comment: "monster object"
+table Monster {
+ pos:Vec3 (id: 0);
+ hp:short = 100 (id: 2);
+ mana:short = 150 (id: 1);
+ name:string (id: 3, key);
+ color:Color = Blue (id: 6);
+ inventory:[ubyte] (id: 5);
+ testarrayoftables:[Monster] (id: 4);
+}
+
+root_type Monster;
diff --git a/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/fuzzer_generated.swift b/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/fuzzer_generated.swift
new file mode 100644
index 00000000..dffeaa87
--- /dev/null
+++ b/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/fuzzer_generated.swift
@@ -0,0 +1,224 @@
+// automatically generated by the FlatBuffers compiler, do not modify
+// swiftlint:disable all
+// swiftformat:disable all
+
+import FlatBuffers
+
+public enum Color: UInt8, Enum, Verifiable {
+ public typealias T = UInt8
+ public static var byteSize: Int { return MemoryLayout<UInt8>.size }
+ public var value: UInt8 { return self.rawValue }
+ case red = 1
+ /// \brief color Green
+ /// Green is bit_flag with value (1u << 1)
+ case green = 2
+ /// \brief color Blue (1u << 3)
+ case blue = 8
+
+ public static var max: Color { return .blue }
+ public static var min: Color { return .red }
+}
+
+public struct Test: NativeStruct, Verifiable {
+
+ static func validateVersion() { FlatBuffersVersion_2_0_0() }
+
+ private var _a: Int16
+ private var _b: Int8
+ private let padding0__: UInt8 = 0
+
+ public init(a: Int16, b: Int8) {
+ _a = a
+ _b = b
+ }
+
+ public init() {
+ _a = 0
+ _b = 0
+ }
+
+ public var a: Int16 { _a }
+ public var b: Int8 { _b }
+
+ public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
+ try verifier.inBuffer(position: position, of: Test.self)
+ }
+}
+
+public struct Test_Mutable: FlatBufferObject {
+
+ static func validateVersion() { FlatBuffersVersion_2_0_0() }
+ public var __buffer: ByteBuffer! { return _accessor.bb }
+ private var _accessor: Struct
+
+ public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) }
+
+ public var a: Int16 { return _accessor.readBuffer(of: Int16.self, at: 0) }
+ public var b: Int8 { return _accessor.readBuffer(of: Int8.self, at: 2) }
+}
+
+public struct Vec3: NativeStruct, Verifiable {
+
+ static func validateVersion() { FlatBuffersVersion_2_0_0() }
+
+ private var _x: Float32
+ private var _y: Float32
+ private var _z: Float32
+ private let padding0__: UInt32 = 0
+ private var _test1: Double
+ private var _test2: UInt8
+ private let padding1__: UInt8 = 0
+ private var _test3: Test
+ private let padding2__: UInt16 = 0
+
+ public init(x: Float32, y: Float32, z: Float32, test1: Double, test2: Color, test3: Test) {
+ _x = x
+ _y = y
+ _z = z
+ _test1 = test1
+ _test2 = test2.value
+ _test3 = test3
+ }
+
+ public init() {
+ _x = 0.0
+ _y = 0.0
+ _z = 0.0
+ _test1 = 0.0
+ _test2 = 0
+ _test3 = Test()
+ }
+
+ public var x: Float32 { _x }
+ public var y: Float32 { _y }
+ public var z: Float32 { _z }
+ public var test1: Double { _test1 }
+ public var test2: Color { Color(rawValue: _test2)! }
+ public var test3: Test { _test3 }
+
+ public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
+ try verifier.inBuffer(position: position, of: Vec3.self)
+ }
+}
+
+public struct Vec3_Mutable: FlatBufferObject {
+
+ static func validateVersion() { FlatBuffersVersion_2_0_0() }
+ public var __buffer: ByteBuffer! { return _accessor.bb }
+ private var _accessor: Struct
+
+ public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) }
+
+ public var x: Float32 { return _accessor.readBuffer(of: Float32.self, at: 0) }
+ public var y: Float32 { return _accessor.readBuffer(of: Float32.self, at: 4) }
+ public var z: Float32 { return _accessor.readBuffer(of: Float32.self, at: 8) }
+ public var test1: Double { return _accessor.readBuffer(of: Double.self, at: 16) }
+ public var test2: Color { return Color(rawValue: _accessor.readBuffer(of: UInt8.self, at: 24)) ?? .red }
+ public var test3: Test_Mutable { return Test_Mutable(_accessor.bb, o: _accessor.postion + 26) }
+}
+
+/// an example documentation comment: "monster object"
+public struct Monster: FlatBufferObject, Verifiable {
+
+ static func validateVersion() { FlatBuffersVersion_2_0_0() }
+ public var __buffer: ByteBuffer! { return _accessor.bb }
+ private var _accessor: Table
+
+ public static func getRootAsMonster(bb: ByteBuffer) -> Monster { return Monster(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 pos = 4
+ case mana = 6
+ case hp = 8
+ case name = 10
+ case testarrayoftables = 12
+ case inventory = 14
+ case color = 16
+ var v: Int32 { Int32(self.rawValue) }
+ var p: VOffset { self.rawValue }
+ }
+
+ public var pos: Vec3? { let o = _accessor.offset(VTOFFSET.pos.v); return o == 0 ? nil : _accessor.readBuffer(of: Vec3.self, at: o) }
+ public var mutablePos: Vec3_Mutable? { let o = _accessor.offset(VTOFFSET.pos.v); return o == 0 ? nil : Vec3_Mutable(_accessor.bb, o: o + _accessor.postion) }
+ public var mana: Int16 { let o = _accessor.offset(VTOFFSET.mana.v); return o == 0 ? 150 : _accessor.readBuffer(of: Int16.self, at: o) }
+ public var hp: Int16 { let o = _accessor.offset(VTOFFSET.hp.v); return o == 0 ? 100 : _accessor.readBuffer(of: Int16.self, at: o) }
+ public var name: String! { let o = _accessor.offset(VTOFFSET.name.v); return _accessor.string(at: o) }
+ public var nameSegmentArray: [UInt8]! { return _accessor.getVector(at: VTOFFSET.name.v) }
+ public var testarrayoftablesCount: Int32 { let o = _accessor.offset(VTOFFSET.testarrayoftables.v); return o == 0 ? 0 : _accessor.vector(count: o) }
+ public func testarrayoftables(at index: Int32) -> Monster? { let o = _accessor.offset(VTOFFSET.testarrayoftables.v); return o == 0 ? nil : Monster(_accessor.bb, o: _accessor.indirect(_accessor.vector(at: o) + index * 4)) }
+ public func testarrayoftablesBy(key: String) -> Monster? { let o = _accessor.offset(VTOFFSET.testarrayoftables.v); return o == 0 ? nil : Monster.lookupByKey(vector: _accessor.vector(at: o), key: key, fbb: _accessor.bb) }
+ public var inventoryCount: Int32 { let o = _accessor.offset(VTOFFSET.inventory.v); return o == 0 ? 0 : _accessor.vector(count: o) }
+ public func inventory(at index: Int32) -> UInt8 { let o = _accessor.offset(VTOFFSET.inventory.v); return o == 0 ? 0 : _accessor.directRead(of: UInt8.self, offset: _accessor.vector(at: o) + index * 1) }
+ public var inventory: [UInt8] { return _accessor.getVector(at: VTOFFSET.inventory.v) ?? [] }
+ public var color: Color { let o = _accessor.offset(VTOFFSET.color.v); return o == 0 ? .blue : Color(rawValue: _accessor.readBuffer(of: UInt8.self, at: o)) ?? .blue }
+ public static func startMonster(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 7) }
+ public static func add(pos: Vec3?, _ fbb: inout FlatBufferBuilder) { guard let pos = pos else { return }; fbb.create(struct: pos, position: VTOFFSET.pos.p) }
+ public static func add(mana: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: mana, def: 150, at: VTOFFSET.mana.p) }
+ public static func add(hp: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: hp, def: 100, at: VTOFFSET.hp.p) }
+ public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VTOFFSET.name.p) }
+ public static func addVectorOf(testarrayoftables: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: testarrayoftables, at: VTOFFSET.testarrayoftables.p) }
+ public static func addVectorOf(inventory: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: inventory, at: VTOFFSET.inventory.p) }
+ public static func add(color: Color, _ fbb: inout FlatBufferBuilder) { fbb.add(element: color.rawValue, def: 8, at: VTOFFSET.color.p) }
+ public static func endMonster(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); fbb.require(table: end, fields: [10]); return end }
+ public static func createMonster(
+ _ fbb: inout FlatBufferBuilder,
+ pos: Vec3? = nil,
+ mana: Int16 = 150,
+ hp: Int16 = 100,
+ nameOffset name: Offset = Offset(),
+ testarrayoftablesVectorOffset testarrayoftables: Offset = Offset(),
+ inventoryVectorOffset inventory: Offset = Offset(),
+ color: Color = .blue
+ ) -> Offset {
+ let __start = Monster.startMonster(&fbb)
+ Monster.add(pos: pos, &fbb)
+ Monster.add(mana: mana, &fbb)
+ Monster.add(hp: hp, &fbb)
+ Monster.add(name: name, &fbb)
+ Monster.addVectorOf(testarrayoftables: testarrayoftables, &fbb)
+ Monster.addVectorOf(inventory: inventory, &fbb)
+ Monster.add(color: color, &fbb)
+ return Monster.endMonster(&fbb, start: __start)
+ }
+ public static func sortVectorOfMonster(offsets:[Offset], _ fbb: inout FlatBufferBuilder) -> Offset {
+ var off = offsets
+ off.sort { Table.compare(Table.offset(Int32($1.o), vOffset: 10, fbb: fbb.buffer), Table.offset(Int32($0.o), vOffset: 10, fbb: fbb.buffer), fbb: fbb.buffer) < 0 }
+ return fbb.createVector(ofOffsets: off)
+ }
+ fileprivate static func lookupByKey(vector: Int32, key: String, fbb: ByteBuffer) -> Monster? {
+ let key = key.utf8.map { $0 }
+ var span = fbb.read(def: Int32.self, position: Int(vector - 4))
+ var start: Int32 = 0
+ while span != 0 {
+ var middle = span / 2
+ let tableOffset = Table.indirect(vector + 4 * (start + middle), fbb)
+ let comp = Table.compare(Table.offset(Int32(fbb.capacity) - tableOffset, vOffset: 10, fbb: fbb), key, fbb: fbb)
+ if comp > 0 {
+ span = middle
+ } else if comp < 0 {
+ middle += 1
+ start += middle
+ span -= middle
+ } else {
+ return Monster(fbb, o: tableOffset)
+ }
+ }
+ return nil
+ }
+
+ 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.pos.p, fieldName: "pos", required: false, type: Vec3.self)
+ try _v.visit(field: VTOFFSET.mana.p, fieldName: "mana", required: false, type: Int16.self)
+ try _v.visit(field: VTOFFSET.hp.p, fieldName: "hp", required: false, type: Int16.self)
+ try _v.visit(field: VTOFFSET.name.p, fieldName: "name", required: true, type: ForwardOffset<String>.self)
+ try _v.visit(field: VTOFFSET.testarrayoftables.p, fieldName: "testarrayoftables", required: false, type: ForwardOffset<Vector<ForwardOffset<Monster>, Monster>>.self)
+ try _v.visit(field: VTOFFSET.inventory.p, fieldName: "inventory", required: false, type: ForwardOffset<Vector<UInt8, UInt8>>.self)
+ try _v.visit(field: VTOFFSET.color.p, fieldName: "color", required: false, type: Color.self)
+ _v.finish()
+ }
+}
+
diff --git a/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/main.swift b/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/main.swift
index a5a23a67..86e422c6 100644
--- a/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/main.swift
+++ b/tests/FlatBuffers.Test.Swift/Sources/SwiftFlatBuffers/main.swift
@@ -14,5 +14,16 @@
* limitations under the License.
*/
-import Foundation
-print("Flatbuffers")
+import FlatBuffers
+
+@_cdecl("LLVMFuzzerTestOneInput")
+public func FuzzFlatbuffers(_ start: UnsafeRawPointer, _ count: Int) -> CInt {
+ let bytes = UnsafeRawBufferPointer(start: start, count: count)
+ do {
+ var buffer = ByteBuffer(contiguousBytes: bytes, count: count)
+ let _: Monster = try getCheckedRoot(byteBuffer: &buffer)
+ } catch {
+ }
+
+ return 0
+}
diff --git a/tests/FlatBuffers.Test.Swift/SwiftTest.sh b/tests/FlatBuffers.Test.Swift/SwiftTest.sh
index 5e1c6cdd..7edf8177 100755
--- a/tests/FlatBuffers.Test.Swift/SwiftTest.sh
+++ b/tests/FlatBuffers.Test.Swift/SwiftTest.sh
@@ -9,5 +9,17 @@ fbc --swift --gen-mutable --grpc --gen-object-api -I ${test_dir}/include_test ${
fbc --swift ${test_dir}/optional_scalars.fbs
fbc --swift --gen-object-api ${test_dir}/more_defaults.fbs
cd ${swift_dir}
+
+cd ${swift_dir}/Sources/SwiftFlatBuffers
+# create better fuzzing test file
+fbc --swift fuzzer.fbs
+cd ${swift_dir}
+
swift build --build-tests
swift test
+
+if [ $(uname -s) != Darwin ]; then
+ echo fuzzing
+ swift build -c debug -Xswiftc -sanitize=fuzzer,address -Xswiftc -parse-as-library
+ swift build -c release -Xswiftc -sanitize=fuzzer,address -Xswiftc -parse-as-library
+fi
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift
index eb57785f..21c3daf4 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift
@@ -26,9 +26,11 @@ typealias Stat = MyGame_Example_Stat
class FlatBuffersMonsterWriterTests: XCTestCase {
func testData() {
+ // swiftformat:disable all
let data = Data([48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
+ // swiftformat:enable all
let _data = ByteBuffer(data: data)
- readMonster(fb: _data)
+ readVerifiedMonster(fb: _data)
}
func testReadFromOtherLanguages() {
@@ -36,29 +38,36 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon")
guard let data = try? Data(contentsOf: url) else { return }
let _data = ByteBuffer(data: data)
- readMonster(fb: _data)
+ readVerifiedMonster(fb: _data)
}
func testCreateMonster() {
let bytes = createMonster(withPrefix: false)
+ // swiftformat:disable all
XCTAssertEqual(bytes.sizedByteArray, [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
- readMonster(fb: bytes.buffer)
+ // swiftformat:enable all
+ let monster = MyGame_Example_Monster.getRootAsMonster(bb: bytes.buffer)
+ readMonster(monster: monster)
mutateMonster(fb: bytes.buffer)
- readMonster(fb: bytes.buffer)
+ readMonster(monster: monster)
}
func testCreateMonsterResizedBuffer() {
let bytes = createMonster(withPrefix: false)
+ // swiftformat:disable all
XCTAssertEqual(bytes.sizedByteArray, [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
- readMonster(fb: bytes.sizedBuffer)
+ // swiftformat:enable all
+ readVerifiedMonster(fb: bytes.sizedBuffer)
}
func testCreateMonsterPrefixed() {
let bytes = createMonster(withPrefix: true)
+ // swiftformat:disable all
XCTAssertEqual(bytes.sizedByteArray, [44, 1, 0, 0, 44, 0, 0, 0, 77, 79, 78, 83, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
+ // swiftformat:enable all
- let newBuf = FlatBuffersUtils.removeSizePrefix(bb: bytes.buffer)
- readMonster(fb: newBuf)
+ var buffer = bytes.buffer
+ readMonster(monster: getPrefixedSizeRoot(byteBuffer: &buffer))
}
func testCreateMonsterUsingCreateMonsterMethodWithNilPos() {
@@ -77,7 +86,15 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
var fbb = FlatBufferBuilder(initialSize: 1)
let name = fbb.create(string: "Barney")
let mStart = Monster.startMonster(&fbb)
- Monster.add(pos: MyGame_Example_Vec3(x: 10, y: 0, z: 0, test1: 0, test2: .blue, test3: .init()), &fbb)
+ Monster.add(
+ pos: MyGame_Example_Vec3(
+ x: 10,
+ y: 0,
+ z: 0,
+ test1: 0,
+ test2: .blue,
+ test3: .init()),
+ &fbb)
Monster.add(name: name, &fbb)
let root = Monster.endMonster(&fbb, start: mStart)
fbb.finish(offset: root)
@@ -88,9 +105,13 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
}
func testReadMonsterFromUnsafePointerWithoutCopying() {
+ // swiftformat:disable all
var array: [UInt8] = [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0]
+ // swiftformat:enable all
let unpacked = array.withUnsafeMutableBytes { (memory) -> MyGame_Example_MonsterT in
- let bytes = ByteBuffer(assumingMemoryBound: memory.baseAddress!, capacity: memory.count)
+ let bytes = ByteBuffer(
+ assumingMemoryBound: memory.baseAddress!,
+ capacity: memory.count)
var monster = Monster.getRootAsMonster(bb: bytes)
readFlatbufferMonster(monster: &monster)
let unpacked = monster.unpack()
@@ -104,7 +125,10 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
var fbb = FlatBufferBuilder(initialSize: 1)
let name = fbb.create(string: "Frodo")
let bools = fbb.createVector(boolArray)
- let root = Monster.createMonster(&fbb, nameOffset: name, testarrayofboolsVectorOffset: bools)
+ let root = Monster.createMonster(
+ &fbb,
+ nameOffset: name,
+ testarrayofboolsVectorOffset: bools)
fbb.finish(offset: root)
let monster = Monster.getRootAsMonster(bb: fbb.sizedBuffer)
@@ -117,8 +141,13 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
}
}
- func readMonster(fb: ByteBuffer) {
- var monster = Monster.getRootAsMonster(bb: fb)
+ func readVerifiedMonster(fb: ByteBuffer) {
+ var byteBuffer = fb
+ XCTAssertNoThrow(try readMonster(monster: getCheckedRoot(byteBuffer: &byteBuffer) as MyGame_Example_Monster))
+ }
+
+ func readMonster(monster: Monster) {
+ var monster = monster
readFlatbufferMonster(monster: &monster)
let unpacked: MyGame_Example_MonsterT? = monster.unpack()
readObjectApi(monster: unpacked!)
@@ -129,7 +158,11 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
func createMonster(withPrefix prefix: Bool) -> FlatBufferBuilder {
var fbb = FlatBufferBuilder(initialSize: 1)
- let names = [fbb.create(string: "Frodo"), fbb.create(string: "Barney"), fbb.create(string: "Wilma")]
+ let names = [
+ fbb.create(string: "Frodo"),
+ fbb.create(string: "Barney"),
+ fbb.create(string: "Wilma"),
+ ]
var offsets: [Offset] = []
let start1 = Monster.startMonster(&fbb)
Monster.add(name: names[0], &fbb)
@@ -161,7 +194,15 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
let stringTestVector = fbb.createVector(ofOffsets: [test1, test2])
let mStart = Monster.startMonster(&fbb)
- Monster.add(pos: MyGame_Example_Vec3(x: 1, y: 2, z: 3, test1: 3, test2: .green, test3: .init(a: 5, b: 6)), &fbb)
+ Monster.add(
+ pos: MyGame_Example_Vec3(
+ x: 1,
+ y: 2,
+ z: 3,
+ test1: 3,
+ test2: .green,
+ test3: .init(a: 5, b: 6)),
+ &fbb)
Monster.add(hp: 80, &fbb)
Monster.add(name: str, &fbb)
Monster.addVectorOf(inventory: inv, &fbb)
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersTests.swift
index ab5a5187..96cd1f73 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersTests.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersTests.swift
@@ -52,22 +52,36 @@ final class FlatBuffersTests: XCTestCase {
func testCreateFinish() {
var b = FlatBufferBuilder(initialSize: 16)
- let countryOff = Country.createCountry(builder: &b, name: country, log: 200, lan: 100)
+ let countryOff = Country.createCountry(
+ builder: &b,
+ name: country,
+ log: 200,
+ lan: 100)
b.finish(offset: countryOff)
+ // swiftformat:disable all
let v: [UInt8] = [16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 4, 0, 8, 0, 12, 0, 10, 0, 0, 0, 12, 0, 0, 0, 100, 0, 0, 0, 200, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0]
+ // swiftformat:enable all
XCTAssertEqual(b.sizedByteArray, v)
}
func testCreateFinishWithPrefix() {
var b = FlatBufferBuilder(initialSize: 16)
- let countryOff = Country.createCountry(builder: &b, name: country, log: 200, lan: 100)
+ let countryOff = Country.createCountry(
+ builder: &b,
+ name: country,
+ log: 200,
+ lan: 100)
b.finish(offset: countryOff, addPrefix: true)
+ // swiftformat:disable all
let v: [UInt8] = [44, 0, 0, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 4, 0, 8, 0, 12, 0, 10, 0, 0, 0, 12, 0, 0, 0, 100, 0, 0, 0, 200, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0]
+ // swiftformat:enable all
XCTAssertEqual(b.sizedByteArray, v)
}
func testReadCountry() {
+ // swiftformat:disable all
let v: [UInt8] = [16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 4, 0, 8, 0, 12, 0, 10, 0, 0, 0, 12, 0, 0, 0, 100, 0, 0, 0, 200, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0]
+ // swiftformat:enable all
let buffer = ByteBuffer(bytes: v)
let c = Country.getRootAsCountry(buffer)
XCTAssertEqual(c.lan, 100)
@@ -115,14 +129,20 @@ class Country {
__t = t
}
- var lan: Int32 { let o = __t.offset(6); return o == 0 ? 0 : __t.readBuffer(of: Int32.self, at: o) }
- var log: Int32 { let o = __t.offset(8); return o == 0 ? 0 : __t.readBuffer(of: Int32.self, at: o) }
+ var lan: Int32 { let o = __t.offset(6); return o == 0 ? 0 : __t.readBuffer(
+ of: Int32.self,
+ at: o) }
+ var log: Int32 { let o = __t.offset(8); return o == 0 ? 0 : __t.readBuffer(
+ of: Int32.self,
+ at: o) }
var nameVector: [UInt8]? { __t.getVector(at: 4) }
var name: String? { let o = __t.offset(4); return o == 0 ? nil : __t.string(at: o) }
@inlinable
static func getRootAsCountry(_ bb: ByteBuffer) -> Country {
- Country(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: 0))))
+ Country(Table(
+ bb: bb,
+ position: Int32(bb.read(def: UOffset.self, position: 0))))
}
@inlinable
@@ -132,7 +152,11 @@ class Country {
log: Int32,
lan: Int32) -> Offset
{
- createCountry(builder: &builder, offset: builder.create(string: name), log: log, lan: lan)
+ createCountry(
+ builder: &builder,
+ offset: builder.create(string: name),
+ log: log,
+ lan: lan)
}
@inlinable
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift
index 9addb81b..5b59b4ed 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift
@@ -34,7 +34,9 @@ final class FlatBuffersUnionTests: XCTestCase {
equippedOffset: weapon.o)
b.finish(offset: root)
let buffer = b.sizedByteArray
+ // swiftformat:disable all
XCTAssertEqual(buffer, [16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 8, 0, 7, 0, 12, 0, 10, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 20, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 8, 0, 12, 0, 8, 0, 6, 0, 8, 0, 0, 0, 0, 0, 5, 0, 4, 0, 0, 0, 3, 0, 0, 0, 65, 120, 101, 0])
+ // swiftformat:enable all
let monster = LocalMonster.getRootAsMonster(bb: ByteBuffer(bytes: buffer))
XCTAssertEqual(monster.weapon(at: 0)?.dmg, dmg)
XCTAssertEqual(monster.weapon(at: 0)?.name, str)
@@ -71,7 +73,9 @@ final class FlatBuffersUnionTests: XCTestCase {
equippedOffset: weaponTwo,
path: path)
builder.finish(offset: orc)
+ // swiftformat:disable all
XCTAssertEqual(builder.sizedByteArray, [32, 0, 0, 0, 0, 0, 26, 0, 48, 0, 36, 0, 0, 0, 34, 0, 28, 0, 0, 0, 24, 0, 23, 0, 16, 0, 15, 0, 8, 0, 4, 0, 26, 0, 0, 0, 44, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 76, 0, 0, 0, 0, 0, 44, 1, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 0, 0, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192, 64, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 0, 0, 52, 0, 0, 0, 28, 0, 0, 0, 10, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 3, 0, 0, 0, 79, 114, 99, 0, 244, 255, 255, 255, 0, 0, 5, 0, 24, 0, 0, 0, 8, 0, 12, 0, 8, 0, 6, 0, 8, 0, 0, 0, 0, 0, 3, 0, 12, 0, 0, 0, 3, 0, 0, 0, 65, 120, 101, 0, 5, 0, 0, 0, 83, 119, 111, 114, 100, 0, 0, 0])
+ // swiftformat:enable all
}
func testEnumVector() {
@@ -83,7 +87,9 @@ final class FlatBuffersUnionTests: XCTestCase {
ColorsNameSpace.Monster.add(colors: off, &builder)
let end = ColorsNameSpace.Monster.endMonster(&builder, start: start)
builder.finish(offset: end)
+ // swiftformat:disable all
XCTAssertEqual(builder.sizedByteArray, [12, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0])
+ // swiftformat:enable all
let monster = ColorsNameSpace.Monster.getRootAsMonster(bb: builder.buffer)
XCTAssertEqual(monster.colorsCount, 2)
XCTAssertEqual(monster.colors(at: 0), .blue)
@@ -121,22 +127,36 @@ final class FlatBuffersUnionTests: XCTestCase {
XCTAssertEqual(movie.charactersType(at: i), characterType[Int(i)])
}
- XCTAssertEqual(movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, 7)
- XCTAssertEqual(movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage, swordDmg)
- XCTAssertEqual(movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead, 2)
+ XCTAssertEqual(
+ movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
+ 7)
+ XCTAssertEqual(
+ movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage,
+ swordDmg)
+ XCTAssertEqual(
+ movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead,
+ 2)
var objc: MovieT? = movie.unpack()
XCTAssertEqual(movie.charactersTypeCount, Int32(objc?.characters.count ?? 0))
- XCTAssertEqual(movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, (objc?.characters[0]?.value as? BookReader)?.booksRead)
+ XCTAssertEqual(
+ movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
+ (objc?.characters[0]?.value as? BookReader)?.booksRead)
fb.clear()
let newMovie = Movie.pack(&fb, obj: &objc)
fb.finish(offset: newMovie)
let packedMovie = Movie.getRootAsMovie(bb: fb.buffer)
- XCTAssertEqual(packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead)
- XCTAssertEqual(packedMovie.characters(at: 1, type: Attacker.self)?.swordAttackDamage, movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage)
- XCTAssertEqual(packedMovie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead, movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead)
+ XCTAssertEqual(
+ packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
+ movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead)
+ XCTAssertEqual(
+ packedMovie.characters(at: 1, type: Attacker.self)?.swordAttackDamage,
+ movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage)
+ XCTAssertEqual(
+ packedMovie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead,
+ movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead)
}
func testStringUnion() {
@@ -162,7 +182,9 @@ final class FlatBuffersUnionTests: XCTestCase {
var movie = Movie.getRootAsMovie(bb: fb.sizedBuffer)
XCTAssertEqual(movie.mainCharacter(type: String.self), string)
- XCTAssertEqual(movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, 7)
+ XCTAssertEqual(
+ movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
+ 7)
XCTAssertEqual(movie.characters(at: 1, type: String.self), string)
var objc: MovieT? = movie.unpack()
@@ -175,7 +197,9 @@ final class FlatBuffersUnionTests: XCTestCase {
let packedMovie = Movie.getRootAsMovie(bb: fb.buffer)
XCTAssertEqual(packedMovie.mainCharacter(type: String.self), string)
- XCTAssertEqual(packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, 7)
+ XCTAssertEqual(
+ packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
+ 7)
XCTAssertEqual(packedMovie.characters(at: 1, type: String.self), string)
}
}
@@ -239,7 +263,10 @@ struct FinalMonster {
builder.add(offset: inventory, at: 14)
builder.add(element: color.rawValue, def: Color3.green.rawValue, at: 16)
builder.add(offset: weapons, at: 18)
- builder.add(element: equipment.rawValue, def: Equipment.none.rawValue, at: 20)
+ builder.add(
+ element: equipment.rawValue,
+ def: Equipment.none.rawValue,
+ at: 20)
builder.add(offset: equippedOffset, at: 22)
builder.add(offset: path, at: 24)
return Offset(offset: builder.endTable(at: start))
@@ -262,7 +289,9 @@ struct LocalMonster {
}
static func getRootAsMonster(bb: ByteBuffer) -> LocalMonster {
- LocalMonster(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: 0))))
+ LocalMonster(Table(
+ bb: bb,
+ position: Int32(bb.read(def: UOffset.self, position: 0))))
}
@inlinable
@@ -290,11 +319,15 @@ struct Weapon: FlatBufferObject {
init(_ t: Table) { __t = t }
init(_ fb: ByteBuffer, o: Int32) { __t = Table(bb: fb, position: o)}
- var dmg: Int16 { let o = __t.offset(6); return o == 0 ? 0 : __t.readBuffer(of: Int16.self, at: o) }
+ var dmg: Int16 { let o = __t.offset(6); return o == 0 ? 0 : __t.readBuffer(
+ of: Int16.self,
+ at: o) }
var nameVector: [UInt8]? { __t.getVector(at: 4) }
var name: String? { let o = __t.offset(4); return o == 0 ? nil : __t.string(at: o) }
- static func assign(_ i: Int32, _ bb: ByteBuffer) -> Weapon { Weapon(Table(bb: bb, position: i)) }
+ static func assign(_ i: Int32, _ bb: ByteBuffer) -> Weapon { Weapon(Table(
+ bb: bb,
+ position: i)) }
@inlinable
static func createWeapon(
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersVectorsTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersVectorsTests.swift
index 9f0db17c..ccccf751 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersVectorsTests.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersVectorsTests.swift
@@ -30,7 +30,9 @@ final class FlatBuffersVectors: XCTestCase {
let vector = [n, d]
let vectorOffset = b.createVector(ofOffsets: vector)
b.finish(offset: vectorOffset)
+ // swiftformat:disable all
XCTAssertEqual(b.sizedByteArray, [4, 0, 0, 0, 2, 0, 0, 0, 48, 0, 0, 0, 16, 0, 0, 0, 0, 0, 10, 0, 18, 0, 4, 0, 8, 0, 12, 0, 10, 0, 0, 0, 40, 0, 0, 0, 100, 0, 0, 0, 200, 0, 0, 0, 0, 0, 10, 0, 16, 0, 4, 0, 8, 0, 12, 0, 10, 0, 0, 0, 24, 0, 0, 0, 188, 2, 0, 0, 120, 3, 0, 0, 7, 0, 0, 0, 68, 101, 110, 109, 97, 114, 107, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0])
+ // swiftformat:enable all
}
func testCreateIntArray() {
@@ -38,7 +40,9 @@ final class FlatBuffersVectors: XCTestCase {
var b = FlatBufferBuilder(initialSize: 20)
let o = b.createVector(numbers, size: numbers.count)
b.finish(offset: o)
+ // swiftformat:disable all
XCTAssertEqual(b.sizedByteArray, [4, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0])
+ // swiftformat:enable all
}
func testCreateEmptyIntArray() {
@@ -54,7 +58,9 @@ final class FlatBuffersVectors: XCTestCase {
var b = FlatBufferBuilder(initialSize: 20)
let o = b.createVector(ofStrings: strs)
b.finish(offset: o)
+ // swiftformat:disable all
XCTAssertEqual(b.sizedByteArray, [4, 0, 0, 0, 2, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0, 7, 0, 0, 0, 68, 101, 110, 109, 97, 114, 107, 0])
+ // swiftformat:enable all
}
func testCreateSharedStringVector() {
let norway = "Norway"
@@ -67,7 +73,9 @@ final class FlatBuffersVectors: XCTestCase {
let v = [noStr, deStr, _noStr, _deStr]
let end = b.createVector(ofOffsets: v)
b.finish(offset: end)
+ // swiftformat:disable all
XCTAssertEqual(b.sizedByteArray, [4, 0, 0, 0, 4, 0, 0, 0, 28, 0, 0, 0, 12, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 68, 101, 110, 109, 97, 114, 107, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0])
+ // swiftformat:enable all
}
func testReadInt32Array() {
@@ -101,7 +109,9 @@ struct Numbers {
@inlinable
static func getRootAsNumbers(_ bb: ByteBuffer) -> Numbers {
- Numbers(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: 0))))
+ Numbers(Table(
+ bb: bb,
+ position: Int32(bb.read(def: UOffset.self, position: 0))))
}
var vArrayInt: [Int]? { __t.getVector(at: 4) }
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersDoubleTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersDoubleTests.swift
index b9b80862..660d5245 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersDoubleTests.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersDoubleTests.swift
@@ -23,17 +23,39 @@ final class FlatBuffersDoubleTests: XCTestCase {
func testCreateFinish() {
var b = FlatBufferBuilder(initialSize: 16)
- let countryOff = CountryDouble.createCountry(builder: &b, name: country, log: 200, lan: 100)
+ let countryOff = CountryDouble.createCountry(
+ builder: &b,
+ name: country,
+ log: 200,
+ lan: 100)
b.finish(offset: countryOff)
- let v: [UInt8] = [16, 0, 0, 0, 0, 0, 10, 0, 28, 0, 4, 0, 8, 0, 16, 0, 10, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 64, 0, 0, 0, 0, 0, 0, 105, 64, 0, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0]
+ // swiftformat:disable all
+ let v: [UInt8] = [
+ 16, 0, 0, 0, 0, 0, 10, 0, 28, 0, 4, 0, 8, 0, 16, 0, 10,
+ 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 64, 0, 0, 0,
+ 0, 0, 0, 105, 64, 0, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119,
+ 97, 121, 0, 0
+ ]
+ // swiftformat:enable all
XCTAssertEqual(b.sizedByteArray, v)
}
func testCreateFinishWithPrefix() {
var b = FlatBufferBuilder(initialSize: 16)
- let countryOff = CountryDouble.createCountry(builder: &b, name: country, log: 200, lan: 100)
+ let countryOff = CountryDouble.createCountry(
+ builder: &b,
+ name: country,
+ log: 200,
+ lan: 100)
b.finish(offset: countryOff, addPrefix: true)
- let v: [UInt8] = [60, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 28, 0, 4, 0, 8, 0, 16, 0, 10, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 64, 0, 0, 0, 0, 0, 0, 105, 64, 0, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0]
+ // swiftformat:disable all
+ let v: [UInt8] = [
+ 60, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 28
+ , 0, 4, 0, 8, 0, 16, 0, 10, 0, 0, 0, 24, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 89, 64, 0, 0, 0, 0, 0, 0, 105, 64, 0, 0, 0,
+ 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0
+ ]
+ // swiftformat:enable all
XCTAssertEqual(b.sizedByteArray, v)
}
}
@@ -57,7 +79,11 @@ class CountryDouble {
log: Double,
lan: Double) -> Offset
{
- createCountry(builder: &builder, offset: builder.create(string: name), log: log, lan: lan)
+ createCountry(
+ builder: &builder,
+ offset: builder.create(string: name),
+ log: log,
+ lan: lan)
}
static func createCountry(
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersVerifierTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersVerifierTests.swift
new file mode 100644
index 00000000..dd80abf8
--- /dev/null
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersVerifierTests.swift
@@ -0,0 +1,238 @@
+/*
+ * 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 XCTest
+@testable import FlatBuffers
+
+final class FlatbuffersVerifierTests: XCTestCase {
+
+ lazy var validStorage: ByteBuffer.Storage = ByteBuffer.Storage(
+ count: Int(FlatBufferMaxSize) - 1,
+ alignment: 1)
+ lazy var errorStorage: ByteBuffer.Storage = ByteBuffer.Storage(
+ count: Int(FlatBufferMaxSize) + 1,
+ alignment: 1)
+
+ var buffer: ByteBuffer!
+
+ var validFlatbuffersObject: ByteBuffer!
+ var invalidFlatbuffersObject: ByteBuffer!
+
+ override func setUp() {
+ // swiftformat:disable all
+ buffer = ByteBuffer(initialSize: 32)
+ add(buffer: &buffer, v: 4, p: 16)
+ add(buffer: &buffer, v: 4, p: 20)
+
+ validFlatbuffersObject = ByteBuffer(bytes: [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
+
+ invalidFlatbuffersObject = ByteBuffer(bytes: [0, 48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
+
+ // swiftformat:enable all
+ }
+
+ func testVeriferInitPassing() {
+ var buffer = ByteBuffer(initialSize: 0)
+ buffer._storage = validStorage
+ XCTAssertNoThrow(try Verifier(buffer: &buffer))
+ }
+
+ func testVeriferInitFailing() {
+ var buffer = ByteBuffer(initialSize: 0)
+ buffer._storage = errorStorage
+ XCTAssertThrowsError(try Verifier(buffer: &buffer))
+ }
+
+ func testVerifierCheckAlignment() {
+ var verifier = try! Verifier(buffer: &buffer)
+ do {
+ try verifier.isAligned(position: 20, type: Int.self)
+ } catch {
+ XCTAssertEqual(
+ error as? FlatbuffersErrors,
+ .missAlignedPointer(position: 20, type: "Int"))
+ }
+ XCTAssertNoThrow(try verifier.isAligned(position: 16, type: Int.self))
+
+ var newVerifer = try! Verifier(buffer: &buffer, checkAlignment: false)
+ XCTAssertNoThrow(try newVerifer.isAligned(position: 16, type: Int.self))
+ }
+
+ func testRangeInBuffer() {
+ var verifier = try! Verifier(buffer: &buffer)
+ let size = MemoryLayout<Int64>.size
+ XCTAssertNoThrow(try verifier.rangeInBuffer(position: 24, size: size))
+ XCTAssertThrowsError(try verifier.rangeInBuffer(position: 26, size: size))
+ XCTAssertThrowsError(try verifier.rangeInBuffer(position: 26, size: size))
+ XCTAssertThrowsError(try verifier.rangeInBuffer(position: 30, size: size))
+ XCTAssertThrowsError(try verifier.rangeInBuffer(position: 32, size: size))
+ XCTAssertThrowsError(try verifier.rangeInBuffer(position: 34, size: size))
+
+ verifier = try! Verifier(
+ buffer: &buffer,
+ options: .init(maxDepth: 0, maxTableCount: 0, maxApparentSize: 4))
+ do {
+ try verifier.rangeInBuffer(position: 24, size: size)
+ } catch {
+ XCTAssertEqual(
+ error as! FlatbuffersErrors,
+ .apparentSizeTooLarge)
+ }
+ }
+
+ func testPositionInBuffer() {
+ var verifier = try! Verifier(buffer: &buffer)
+ XCTAssertNoThrow(try verifier.inBuffer(position: 0, of: Int64.self))
+ XCTAssertNoThrow(try verifier.inBuffer(position: 24, of: Int64.self))
+ XCTAssertThrowsError(try verifier.inBuffer(position: -9, of: Int64.self))
+ XCTAssertThrowsError(try verifier.inBuffer(position: 25, of: Int64.self))
+ XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int32.self))
+ XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int64.self))
+ XCTAssertThrowsError(try verifier.inBuffer(position: 30, of: Int64.self))
+ XCTAssertThrowsError(try verifier.inBuffer(position: 32, of: Int64.self))
+ XCTAssertThrowsError(try verifier.inBuffer(position: 34, of: Int64.self))
+ }
+
+ func testVisitTable() {
+ var verifier = try! Verifier(buffer: &validFlatbuffersObject)
+ XCTAssertNoThrow(try verifier.visitTable(at: 48))
+ verifier.reset()
+ }
+
+ func testTableVerifier() {
+ var verifier = try! Verifier(buffer: &validFlatbuffersObject)
+
+ var tableVerifer = try! verifier.visitTable(at: 48)
+ XCTAssertNoThrow(try tableVerifer.visit(
+ field: 4,
+ fieldName: "Vec",
+ required: false,
+ type: Vec3.self))
+ XCTAssertNoThrow(try tableVerifer.visit(
+ field: 8,
+ fieldName: "hp",
+ required: false,
+ type: Int16.self))
+
+ XCTAssertNoThrow(try tableVerifer.visit(
+ field: 10,
+ fieldName: "name",
+ required: true,
+ type: ForwardOffset<String>.self))
+
+ XCTAssertNoThrow(try tableVerifer.visit(
+ field: 14,
+ fieldName: "inventory",
+ required: false,
+ type: ForwardOffset<Vector<UInt8, UInt8>>.self))
+
+ XCTAssertNoThrow(try tableVerifer.visit(
+ field: 22,
+ fieldName: "test4",
+ required: false,
+ type: ForwardOffset<Vector<MyGame_Example_Test, MyGame_Example_Test>>.self))
+
+ XCTAssertNoThrow(try tableVerifer.visit(
+ field: 24,
+ fieldName: "Vector of strings",
+ required: false,
+ type: ForwardOffset<Vector<ForwardOffset<String>, String>>.self))
+
+ do {
+ try tableVerifer.visit(
+ field: 13,
+ fieldName: "notvalid",
+ required: false,
+ type: Int16.self)
+ } catch {
+ XCTAssertEqual(
+ error as! FlatbuffersErrors,
+ .missAlignedPointer(position: 25, type: "UInt16"))
+ }
+
+ do {
+ try tableVerifer.visit(
+ unionKey: 18,
+ unionField: 20,
+ unionKeyName: "testType",
+ fieldName: "test",
+ required: false,
+ completion: { (verifier, key: MyGame_Example_Any_, pos) in
+ switch key {
+ case .none_:
+ break
+ case .monster:
+ try ForwardOffset<MyGame_Example_Monster>.verify(
+ &verifier,
+ at: pos,
+ of: MyGame_Example_Monster.self)
+
+ case .testsimpletablewithenum:
+ break
+ case .mygameExample2Monster:
+ break
+ }
+ })
+ } catch {
+ XCTAssertEqual(
+ error as! FlatbuffersErrors,
+ .missAlignedPointer(position: 25, type: "UInt16"))
+ }
+ }
+
+ func testVerifyUnionVectors() {
+ // swiftformat:disable all
+ var byteBuffer = ByteBuffer(bytes: [20, 0, 0, 0, 77, 79, 86, 73, 12, 0, 12, 0, 0, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 3, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 12, 0, 0, 0, 3, 0, 0, 0, 3, 1, 4, 0, 2, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0])
+ // swiftformat:enable all
+ XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &byteBuffer) as Movie)
+ }
+
+ func testFullVerifier() {
+ XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &validFlatbuffersObject) as MyGame_Example_Monster)
+ }
+
+ func testInvalidBuffer() {
+ XCTAssertThrowsError(try getCheckedRoot(byteBuffer: &invalidFlatbuffersObject) as MyGame_Example_Monster)
+ }
+
+ func testValidUnionBuffer() {
+ let string = "Awesome \\\\t\t\nstring!"
+ var fb = FlatBufferBuilder()
+ let stringOffset = fb.create(string: string)
+ let characterType: [Character] = [.bookfan, .other]
+
+ let characters = [
+ fb.create(struct: BookReader(booksRead: 7)),
+ stringOffset,
+ ]
+ let types = fb.createVector(characterType)
+ let characterVector = fb.createVector(ofOffsets: characters)
+
+ let end = Movie.createMovie(
+ &fb,
+ mainCharacterType: .other,
+ mainCharacterOffset: Offset(offset: stringOffset.o),
+ charactersTypeVectorOffset: types,
+ charactersVectorOffset: characterVector)
+ Movie.finish(&fb, end: end)
+ var buf = fb.sizedBuffer
+ XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &buf) as Movie)
+ }
+
+ func add(buffer: inout ByteBuffer, v: Int32, p: Int) {
+ buffer.write(value: v, index: p)
+ }
+}
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift
index 8ae91113..9c04bb81 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift
@@ -36,11 +36,17 @@ extension FlatBuffersMonsterWriterTests {
("testCreateMonster", testCreateMonster),
("testCreateMonsterPrefixed", testCreateMonsterPrefixed),
("testCreateMonsterResizedBuffer", testCreateMonsterResizedBuffer),
- ("testCreateMonsterUsingCreateMonsterMethodWithNilPos", testCreateMonsterUsingCreateMonsterMethodWithNilPos),
- ("testCreateMonsterUsingCreateMonsterMethodWithPosX", testCreateMonsterUsingCreateMonsterMethodWithPosX),
+ (
+ "testCreateMonsterUsingCreateMonsterMethodWithNilPos",
+ testCreateMonsterUsingCreateMonsterMethodWithNilPos),
+ (
+ "testCreateMonsterUsingCreateMonsterMethodWithPosX",
+ testCreateMonsterUsingCreateMonsterMethodWithPosX),
("testData", testData),
("testReadFromOtherLanguages", testReadFromOtherLanguages),
- ("testReadMonsterFromUnsafePointerWithoutCopying", testReadMonsterFromUnsafePointerWithoutCopying),
+ (
+ "testReadMonsterFromUnsafePointerWithoutCopying",
+ testReadMonsterFromUnsafePointerWithoutCopying),
]
}
@@ -108,6 +114,25 @@ extension FlatBuffersVectors {
]
}
+extension FlatbuffersVerifierTests {
+ // DO NOT MODIFY: This is autogenerated, use:
+ // `swift test --generate-linuxmain`
+ // to regenerate.
+ static let __allTests__FlatbuffersVerifierTests = [
+ ("testFullVerifier", testFullVerifier),
+ ("testInvalidBuffer", testInvalidBuffer),
+ ("testPositionInBuffer", testPositionInBuffer),
+ ("testRangeInBuffer", testRangeInBuffer),
+ ("testTableVerifier", testTableVerifier),
+ ("testValidUnionBuffer", testValidUnionBuffer),
+ ("testVeriferInitFailing", testVeriferInitFailing),
+ ("testVeriferInitPassing", testVeriferInitPassing),
+ ("testVerifierCheckAlignment", testVerifierCheckAlignment),
+ ("testVerifyUnionVectors", testVerifyUnionVectors),
+ ("testVisitTable", testVisitTable),
+ ]
+}
+
public func __allTests() -> [XCTestCaseEntry] {
[
testCase(FlatBuffersDoubleTests.__allTests__FlatBuffersDoubleTests),
@@ -117,6 +142,7 @@ public func __allTests() -> [XCTestCaseEntry] {
testCase(FlatBuffersTests.__allTests__FlatBuffersTests),
testCase(FlatBuffersUnionTests.__allTests__FlatBuffersUnionTests),
testCase(FlatBuffersVectors.__allTests__FlatBuffersVectors),
+ testCase(FlatbuffersVerifierTests.__allTests__FlatbuffersVerifierTests),
]
}
#endif
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift
index d955bb6c..9925ac3c 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift
@@ -5,7 +5,7 @@
import FlatBuffers
/// Composite components of Monster color.
-public enum MyGame_Example_Color: UInt8, Enum {
+public enum MyGame_Example_Color: UInt8, Enum, Verifiable {
public typealias T = UInt8
public static var byteSize: Int { return MemoryLayout<UInt8>.size }
public var value: UInt8 { return self.rawValue }
@@ -15,13 +15,12 @@ public enum MyGame_Example_Color: UInt8, Enum {
case green = 2
/// \brief color Blue (1u << 3)
case blue = 8
-
public static var max: MyGame_Example_Color { return .blue }
public static var min: MyGame_Example_Color { return .red }
}
-public enum MyGame_Example_Race: Int8, Enum {
+public enum MyGame_Example_Race: Int8, Enum, Verifiable {
public typealias T = Int8
public static var byteSize: Int { return MemoryLayout<Int8>.size }
public var value: Int8 { return self.rawValue }
@@ -29,21 +28,24 @@ public enum MyGame_Example_Race: Int8, Enum {
case human = 0
case dwarf = 1
case elf = 2
-
public static var max: MyGame_Example_Race { return .elf }
public static var min: MyGame_Example_Race { return .none_ }
}
-public enum MyGame_Example_Any_: UInt8, Enum {
+public enum MyGame_Example_Any_: UInt8, UnionEnum {
public typealias T = UInt8
+
+ public init?(value: T) {
+ self.init(rawValue: value)
+ }
+
public static var byteSize: Int { return MemoryLayout<UInt8>.size }
public var value: UInt8 { return self.rawValue }
case none_ = 0
case monster = 1
case testsimpletablewithenum = 2
case mygameExample2Monster = 3
-
public static var max: MyGame_Example_Any_ { return .mygameExample2Monster }
public static var min: MyGame_Example_Any_ { return .none_ }
@@ -71,15 +73,19 @@ public struct MyGame_Example_Any_Union {
}
}
}
-public enum MyGame_Example_AnyUniqueAliases: UInt8, Enum {
+public enum MyGame_Example_AnyUniqueAliases: UInt8, UnionEnum {
public typealias T = UInt8
+
+ public init?(value: T) {
+ self.init(rawValue: value)
+ }
+
public static var byteSize: Int { return MemoryLayout<UInt8>.size }
public var value: UInt8 { return self.rawValue }
case none_ = 0
case m = 1
case ts = 2
case m2 = 3
-
public static var max: MyGame_Example_AnyUniqueAliases { return .m2 }
public static var min: MyGame_Example_AnyUniqueAliases { return .none_ }
@@ -107,15 +113,19 @@ public struct MyGame_Example_AnyUniqueAliasesUnion {
}
}
}
-public enum MyGame_Example_AnyAmbiguousAliases: UInt8, Enum {
+public enum MyGame_Example_AnyAmbiguousAliases: UInt8, UnionEnum {
public typealias T = UInt8
+
+ public init?(value: T) {
+ self.init(rawValue: value)
+ }
+
public static var byteSize: Int { return MemoryLayout<UInt8>.size }
public var value: UInt8 { return self.rawValue }
case none_ = 0
case m1 = 1
case m2 = 2
case m3 = 3
-
public static var max: MyGame_Example_AnyAmbiguousAliases { return .m3 }
public static var min: MyGame_Example_AnyAmbiguousAliases { return .none_ }
@@ -143,7 +153,7 @@ public struct MyGame_Example_AnyAmbiguousAliasesUnion {
}
}
}
-public struct MyGame_Example_Test: NativeStruct, NativeObject {
+public struct MyGame_Example_Test: NativeStruct, Verifiable, NativeObject {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
@@ -168,6 +178,10 @@ public struct MyGame_Example_Test: NativeStruct, NativeObject {
public var a: Int16 { _a }
public var b: Int8 { _b }
+
+ public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
+ try verifier.inBuffer(position: position, of: MyGame_Example_Test.self)
+ }
}
public struct MyGame_Example_Test_Mutable: FlatBufferObject {
@@ -197,7 +211,7 @@ public struct MyGame_Example_Test_Mutable: FlatBufferObject {
}
}
-public struct MyGame_Example_Vec3: NativeStruct, NativeObject {
+public struct MyGame_Example_Vec3: NativeStruct, Verifiable, NativeObject {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
@@ -245,6 +259,10 @@ public struct MyGame_Example_Vec3: NativeStruct, NativeObject {
public var test1: Double { _test1 }
public var test2: MyGame_Example_Color { MyGame_Example_Color(rawValue: _test2)! }
public var test3: MyGame_Example_Test { _test3 }
+
+ public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
+ try verifier.inBuffer(position: position, of: MyGame_Example_Vec3.self)
+ }
}
public struct MyGame_Example_Vec3_Mutable: FlatBufferObject {
@@ -281,7 +299,7 @@ public struct MyGame_Example_Vec3_Mutable: FlatBufferObject {
}
}
-public struct MyGame_Example_Ability: NativeStruct, NativeObject {
+public struct MyGame_Example_Ability: NativeStruct, Verifiable, NativeObject {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
@@ -305,6 +323,10 @@ public struct MyGame_Example_Ability: NativeStruct, NativeObject {
public var id: UInt32 { _id }
public var distance: UInt32 { _distance }
+
+ public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
+ try verifier.inBuffer(position: position, of: MyGame_Example_Ability.self)
+ }
}
public struct MyGame_Example_Ability_Mutable: FlatBufferObject {
@@ -334,7 +356,7 @@ public struct MyGame_Example_Ability_Mutable: FlatBufferObject {
}
}
-public struct MyGame_Example_StructOfStructs: NativeStruct, NativeObject {
+public struct MyGame_Example_StructOfStructs: NativeStruct, Verifiable, NativeObject {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
@@ -366,6 +388,10 @@ public struct MyGame_Example_StructOfStructs: NativeStruct, NativeObject {
public var a: MyGame_Example_Ability { _a }
public var b: MyGame_Example_Test { _b }
public var c: MyGame_Example_Ability { _c }
+
+ public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
+ try verifier.inBuffer(position: position, of: MyGame_Example_StructOfStructs.self)
+ }
}
public struct MyGame_Example_StructOfStructs_Mutable: FlatBufferObject {
@@ -394,7 +420,7 @@ public struct MyGame_Example_StructOfStructs_Mutable: FlatBufferObject {
}
}
-public struct MyGame_InParentNamespace: FlatBufferObject, ObjectAPIPacker {
+public struct MyGame_InParentNamespace: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -422,6 +448,11 @@ public struct MyGame_InParentNamespace: FlatBufferObject, ObjectAPIPacker {
let __root = MyGame_InParentNamespace.startInParentNamespace(&builder)
return MyGame_InParentNamespace.endInParentNamespace(&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)
+ _v.finish()
+ }
}
public class MyGame_InParentNamespaceT: NativeObject {
@@ -436,7 +467,7 @@ public class MyGame_InParentNamespaceT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_InParentNamespace.self) }
}
-public struct MyGame_Example2_Monster: FlatBufferObject, ObjectAPIPacker {
+public struct MyGame_Example2_Monster: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -464,6 +495,11 @@ public struct MyGame_Example2_Monster: FlatBufferObject, ObjectAPIPacker {
let __root = MyGame_Example2_Monster.startMonster(&builder)
return MyGame_Example2_Monster.endMonster(&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)
+ _v.finish()
+ }
}
public class MyGame_Example2_MonsterT: NativeObject {
@@ -478,7 +514,7 @@ public class MyGame_Example2_MonsterT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example2_Monster.self) }
}
-internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferObject, ObjectAPIPacker {
+internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
internal var __buffer: ByteBuffer! { return _accessor.bb }
@@ -524,6 +560,12 @@ internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferObject, Object
MyGame_Example_TestSimpleTableWithEnum.add(color: obj.color, &builder)
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 {
+ 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()
+ }
}
internal class MyGame_Example_TestSimpleTableWithEnumT: NativeObject {
@@ -541,7 +583,7 @@ internal class MyGame_Example_TestSimpleTableWithEnumT: NativeObject {
internal func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_TestSimpleTableWithEnum.self) }
}
-public struct MyGame_Example_Stat: FlatBufferObject, ObjectAPIPacker {
+public struct MyGame_Example_Stat: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -632,6 +674,14 @@ public struct MyGame_Example_Stat: FlatBufferObject, ObjectAPIPacker {
MyGame_Example_Stat.add(count: obj.count, &builder)
return MyGame_Example_Stat.endStat(&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.id.p, fieldName: "id", required: false, type: ForwardOffset<String>.self)
+ try _v.visit(field: VTOFFSET.val.p, fieldName: "val", required: false, type: Int64.self)
+ try _v.visit(field: VTOFFSET.count.p, fieldName: "count", required: false, type: UInt16.self)
+ _v.finish()
+ }
}
public class MyGame_Example_StatT: NativeObject {
@@ -654,7 +704,7 @@ public class MyGame_Example_StatT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Stat.self) }
}
-public struct MyGame_Example_Referrable: FlatBufferObject, ObjectAPIPacker {
+public struct MyGame_Example_Referrable: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -724,6 +774,12 @@ public struct MyGame_Example_Referrable: FlatBufferObject, ObjectAPIPacker {
MyGame_Example_Referrable.add(id: obj.id, &builder)
return MyGame_Example_Referrable.endReferrable(&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.id.p, fieldName: "id", required: false, type: UInt64.self)
+ _v.finish()
+ }
}
public class MyGame_Example_ReferrableT: NativeObject {
@@ -742,7 +798,7 @@ public class MyGame_Example_ReferrableT: NativeObject {
}
/// an example documentation comment: "monster object"
-public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPIPacker {
+public struct MyGame_Example_Monster: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -1253,6 +1309,91 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPIPacker {
MyGame_Example_Monster.addVectorOf(scalarKeySortedTables: __scalarKeySortedTables, &builder)
return MyGame_Example_Monster.endMonster(&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.pos.p, fieldName: "pos", required: false, type: MyGame_Example_Vec3.self)
+ try _v.visit(field: VTOFFSET.mana.p, fieldName: "mana", required: false, type: Int16.self)
+ try _v.visit(field: VTOFFSET.hp.p, fieldName: "hp", required: false, type: Int16.self)
+ try _v.visit(field: VTOFFSET.name.p, fieldName: "name", required: true, type: ForwardOffset<String>.self)
+ try _v.visit(field: VTOFFSET.inventory.p, fieldName: "inventory", required: false, type: ForwardOffset<Vector<UInt8, UInt8>>.self)
+ try _v.visit(field: VTOFFSET.color.p, fieldName: "color", required: false, type: MyGame_Example_Color.self)
+ try _v.visit(unionKey: VTOFFSET.testType.p, unionField: VTOFFSET.test.p, unionKeyName: "testType", fieldName: "test", required: false, completion: { (verifier, key: MyGame_Example_Any_, pos) in
+ switch key {
+ case .none_:
+ break // NOTE - SWIFT doesnt support none
+ case .monster:
+ try ForwardOffset<MyGame_Example_Monster>.verify(&verifier, at: pos, of: MyGame_Example_Monster.self)
+ case .testsimpletablewithenum:
+ try ForwardOffset<MyGame_Example_TestSimpleTableWithEnum>.verify(&verifier, at: pos, of: MyGame_Example_TestSimpleTableWithEnum.self)
+ case .mygameExample2Monster:
+ try ForwardOffset<MyGame_Example2_Monster>.verify(&verifier, at: pos, of: MyGame_Example2_Monster.self)
+ }
+ })
+ try _v.visit(field: VTOFFSET.test4.p, fieldName: "test4", required: false, type: ForwardOffset<Vector<MyGame_Example_Test, MyGame_Example_Test>>.self)
+ try _v.visit(field: VTOFFSET.testarrayofstring.p, fieldName: "testarrayofstring", required: false, type: ForwardOffset<Vector<ForwardOffset<String>, String>>.self)
+ try _v.visit(field: VTOFFSET.testarrayoftables.p, fieldName: "testarrayoftables", required: false, type: ForwardOffset<Vector<ForwardOffset<MyGame_Example_Monster>, MyGame_Example_Monster>>.self)
+ try _v.visit(field: VTOFFSET.enemy.p, fieldName: "enemy", required: false, type: ForwardOffset<MyGame_Example_Monster>.self)
+ try _v.visit(field: VTOFFSET.testnestedflatbuffer.p, fieldName: "testnestedflatbuffer", required: false, type: ForwardOffset<Vector<UInt8, UInt8>>.self)
+ try _v.visit(field: VTOFFSET.testempty.p, fieldName: "testempty", required: false, type: ForwardOffset<MyGame_Example_Stat>.self)
+ try _v.visit(field: VTOFFSET.testbool.p, fieldName: "testbool", required: false, type: Bool.self)
+ try _v.visit(field: VTOFFSET.testhashs32Fnv1.p, fieldName: "testhashs32Fnv1", required: false, type: Int32.self)
+ try _v.visit(field: VTOFFSET.testhashu32Fnv1.p, fieldName: "testhashu32Fnv1", required: false, type: UInt32.self)
+ try _v.visit(field: VTOFFSET.testhashs64Fnv1.p, fieldName: "testhashs64Fnv1", required: false, type: Int64.self)
+ try _v.visit(field: VTOFFSET.testhashu64Fnv1.p, fieldName: "testhashu64Fnv1", required: false, type: UInt64.self)
+ try _v.visit(field: VTOFFSET.testhashs32Fnv1a.p, fieldName: "testhashs32Fnv1a", required: false, type: Int32.self)
+ try _v.visit(field: VTOFFSET.testhashu32Fnv1a.p, fieldName: "testhashu32Fnv1a", required: false, type: UInt32.self)
+ try _v.visit(field: VTOFFSET.testhashs64Fnv1a.p, fieldName: "testhashs64Fnv1a", required: false, type: Int64.self)
+ try _v.visit(field: VTOFFSET.testhashu64Fnv1a.p, fieldName: "testhashu64Fnv1a", required: false, type: UInt64.self)
+ try _v.visit(field: VTOFFSET.testarrayofbools.p, fieldName: "testarrayofbools", required: false, type: ForwardOffset<Vector<Bool, Bool>>.self)
+ try _v.visit(field: VTOFFSET.testf.p, fieldName: "testf", required: false, type: Float32.self)
+ try _v.visit(field: VTOFFSET.testf2.p, fieldName: "testf2", required: false, type: Float32.self)
+ try _v.visit(field: VTOFFSET.testf3.p, fieldName: "testf3", required: false, type: Float32.self)
+ try _v.visit(field: VTOFFSET.testarrayofstring2.p, fieldName: "testarrayofstring2", required: false, type: ForwardOffset<Vector<ForwardOffset<String>, String>>.self)
+ try _v.visit(field: VTOFFSET.testarrayofsortedstruct.p, fieldName: "testarrayofsortedstruct", required: false, type: ForwardOffset<Vector<MyGame_Example_Ability, MyGame_Example_Ability>>.self)
+ try _v.visit(field: VTOFFSET.flex.p, fieldName: "flex", required: false, type: ForwardOffset<Vector<UInt8, UInt8>>.self)
+ try _v.visit(field: VTOFFSET.test5.p, fieldName: "test5", required: false, type: ForwardOffset<Vector<MyGame_Example_Test, MyGame_Example_Test>>.self)
+ try _v.visit(field: VTOFFSET.vectorOfLongs.p, fieldName: "vectorOfLongs", required: false, type: ForwardOffset<Vector<Int64, Int64>>.self)
+ try _v.visit(field: VTOFFSET.vectorOfDoubles.p, fieldName: "vectorOfDoubles", required: false, type: ForwardOffset<Vector<Double, Double>>.self)
+ try _v.visit(field: VTOFFSET.parentNamespaceTest.p, fieldName: "parentNamespaceTest", required: false, type: ForwardOffset<MyGame_InParentNamespace>.self)
+ try _v.visit(field: VTOFFSET.vectorOfReferrables.p, fieldName: "vectorOfReferrables", required: false, type: ForwardOffset<Vector<ForwardOffset<MyGame_Example_Referrable>, MyGame_Example_Referrable>>.self)
+ try _v.visit(field: VTOFFSET.singleWeakReference.p, fieldName: "singleWeakReference", required: false, type: UInt64.self)
+ try _v.visit(field: VTOFFSET.vectorOfWeakReferences.p, fieldName: "vectorOfWeakReferences", required: false, type: ForwardOffset<Vector<UInt64, UInt64>>.self)
+ try _v.visit(field: VTOFFSET.vectorOfStrongReferrables.p, fieldName: "vectorOfStrongReferrables", required: false, type: ForwardOffset<Vector<ForwardOffset<MyGame_Example_Referrable>, MyGame_Example_Referrable>>.self)
+ try _v.visit(field: VTOFFSET.coOwningReference.p, fieldName: "coOwningReference", required: false, type: UInt64.self)
+ try _v.visit(field: VTOFFSET.vectorOfCoOwningReferences.p, fieldName: "vectorOfCoOwningReferences", required: false, type: ForwardOffset<Vector<UInt64, UInt64>>.self)
+ try _v.visit(field: VTOFFSET.nonOwningReference.p, fieldName: "nonOwningReference", required: false, type: UInt64.self)
+ try _v.visit(field: VTOFFSET.vectorOfNonOwningReferences.p, fieldName: "vectorOfNonOwningReferences", required: false, type: ForwardOffset<Vector<UInt64, UInt64>>.self)
+ try _v.visit(unionKey: VTOFFSET.anyUniqueType.p, unionField: VTOFFSET.anyUnique.p, unionKeyName: "anyUniqueType", fieldName: "anyUnique", required: false, completion: { (verifier, key: MyGame_Example_AnyUniqueAliases, pos) in
+ switch key {
+ case .none_:
+ break // NOTE - SWIFT doesnt support none
+ case .m:
+ try ForwardOffset<MyGame_Example_Monster>.verify(&verifier, at: pos, of: MyGame_Example_Monster.self)
+ case .ts:
+ try ForwardOffset<MyGame_Example_TestSimpleTableWithEnum>.verify(&verifier, at: pos, of: MyGame_Example_TestSimpleTableWithEnum.self)
+ case .m2:
+ try ForwardOffset<MyGame_Example2_Monster>.verify(&verifier, at: pos, of: MyGame_Example2_Monster.self)
+ }
+ })
+ try _v.visit(unionKey: VTOFFSET.anyAmbiguousType.p, unionField: VTOFFSET.anyAmbiguous.p, unionKeyName: "anyAmbiguousType", fieldName: "anyAmbiguous", required: false, completion: { (verifier, key: MyGame_Example_AnyAmbiguousAliases, pos) in
+ switch key {
+ case .none_:
+ break // NOTE - SWIFT doesnt support none
+ case .m1:
+ try ForwardOffset<MyGame_Example_Monster>.verify(&verifier, at: pos, of: MyGame_Example_Monster.self)
+ case .m2:
+ try ForwardOffset<MyGame_Example_Monster>.verify(&verifier, at: pos, of: MyGame_Example_Monster.self)
+ case .m3:
+ try ForwardOffset<MyGame_Example_Monster>.verify(&verifier, at: pos, of: MyGame_Example_Monster.self)
+ }
+ })
+ try _v.visit(field: VTOFFSET.vectorOfEnums.p, fieldName: "vectorOfEnums", required: false, type: ForwardOffset<Vector<MyGame_Example_Color, MyGame_Example_Color>>.self)
+ try _v.visit(field: VTOFFSET.signedEnum.p, fieldName: "signedEnum", required: false, type: MyGame_Example_Race.self)
+ try _v.visit(field: VTOFFSET.testrequirednestedflatbuffer.p, fieldName: "testrequirednestedflatbuffer", required: false, type: ForwardOffset<Vector<UInt8, UInt8>>.self)
+ try _v.visit(field: VTOFFSET.scalarKeySortedTables.p, fieldName: "scalarKeySortedTables", required: false, type: ForwardOffset<Vector<ForwardOffset<MyGame_Example_Stat>, MyGame_Example_Stat>>.self)
+ _v.finish()
+ }
}
public class MyGame_Example_MonsterT: NativeObject {
@@ -1505,7 +1646,7 @@ public class MyGame_Example_MonsterT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Monster.self) }
}
-public struct MyGame_Example_TypeAliases: FlatBufferObject, ObjectAPIPacker {
+public struct MyGame_Example_TypeAliases: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -1634,6 +1775,23 @@ public struct MyGame_Example_TypeAliases: FlatBufferObject, ObjectAPIPacker {
MyGame_Example_TypeAliases.addVectorOf(vf64: __vf64, &builder)
return MyGame_Example_TypeAliases.endTypeAliases(&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.i8.p, fieldName: "i8", required: false, type: Int8.self)
+ try _v.visit(field: VTOFFSET.u8.p, fieldName: "u8", required: false, type: UInt8.self)
+ try _v.visit(field: VTOFFSET.i16.p, fieldName: "i16", required: false, type: Int16.self)
+ try _v.visit(field: VTOFFSET.u16.p, fieldName: "u16", required: false, type: UInt16.self)
+ try _v.visit(field: VTOFFSET.i32.p, fieldName: "i32", required: false, type: Int32.self)
+ try _v.visit(field: VTOFFSET.u32.p, fieldName: "u32", required: false, type: UInt32.self)
+ try _v.visit(field: VTOFFSET.i64.p, fieldName: "i64", required: false, type: Int64.self)
+ try _v.visit(field: VTOFFSET.u64.p, fieldName: "u64", required: false, type: UInt64.self)
+ try _v.visit(field: VTOFFSET.f32.p, fieldName: "f32", required: false, type: Float32.self)
+ try _v.visit(field: VTOFFSET.f64.p, fieldName: "f64", required: false, type: Double.self)
+ try _v.visit(field: VTOFFSET.v8.p, fieldName: "v8", required: false, type: ForwardOffset<Vector<Int8, Int8>>.self)
+ try _v.visit(field: VTOFFSET.vf64.p, fieldName: "vf64", required: false, type: ForwardOffset<Vector<Double, Double>>.self)
+ _v.finish()
+ }
}
public class MyGame_Example_TypeAliasesT: NativeObject {
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/more_defaults_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/more_defaults_generated.swift
index aa8d5722..c43bfbc1 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/more_defaults_generated.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/more_defaults_generated.swift
@@ -4,20 +4,19 @@
import FlatBuffers
-public enum ABC: Int32, Enum {
+public enum ABC: Int32, Enum, Verifiable {
public typealias T = Int32
public static var byteSize: Int { return MemoryLayout<Int32>.size }
public var value: Int32 { return self.rawValue }
case a = 0
case b = 1
case c = 2
-
public static var max: ABC { return .c }
public static var min: ABC { return .a }
}
-public struct MoreDefaults: FlatBufferObject, ObjectAPIPacker {
+public struct MoreDefaults: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -118,6 +117,17 @@ public struct MoreDefaults: FlatBufferObject, ObjectAPIPacker {
MoreDefaults.addVectorOf(bools: __bools, &builder)
return MoreDefaults.endMoreDefaults(&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.ints.p, fieldName: "ints", required: false, type: ForwardOffset<Vector<Int32, Int32>>.self)
+ try _v.visit(field: VTOFFSET.floats.p, fieldName: "floats", required: false, type: ForwardOffset<Vector<Float32, Float32>>.self)
+ try _v.visit(field: VTOFFSET.emptyString.p, fieldName: "emptyString", required: false, type: ForwardOffset<String>.self)
+ try _v.visit(field: VTOFFSET.someString.p, fieldName: "someString", required: false, type: ForwardOffset<String>.self)
+ try _v.visit(field: VTOFFSET.abcs.p, fieldName: "abcs", required: false, type: ForwardOffset<Vector<ABC, ABC>>.self)
+ try _v.visit(field: VTOFFSET.bools.p, fieldName: "bools", required: false, type: ForwardOffset<Vector<Bool, Bool>>.self)
+ _v.finish()
+ }
}
public class MoreDefaultsT: NativeObject {
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/optional_scalars_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/optional_scalars_generated.swift
index 85f9555c..4fdd7183 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/optional_scalars_generated.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/optional_scalars_generated.swift
@@ -4,20 +4,19 @@
import FlatBuffers
-public enum optional_scalars_OptionalByte: Int8, Enum {
+public enum optional_scalars_OptionalByte: Int8, Enum, Verifiable {
public typealias T = Int8
public static var byteSize: Int { return MemoryLayout<Int8>.size }
public var value: Int8 { return self.rawValue }
case none_ = 0
case one = 1
case two = 2
-
public static var max: optional_scalars_OptionalByte { return .two }
public static var min: optional_scalars_OptionalByte { return .none_ }
}
-public struct optional_scalars_ScalarStuff: FlatBufferObject {
+public struct optional_scalars_ScalarStuff: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -224,5 +223,46 @@ public struct optional_scalars_ScalarStuff: FlatBufferObject {
optional_scalars_ScalarStuff.add(defaultEnum: defaultEnum, &fbb)
return optional_scalars_ScalarStuff.endScalarStuff(&fbb, start: __start)
}
+
+ 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.justI8.p, fieldName: "justI8", required: false, type: Int8.self)
+ try _v.visit(field: VTOFFSET.maybeI8.p, fieldName: "maybeI8", required: false, type: Int8.self)
+ try _v.visit(field: VTOFFSET.defaultI8.p, fieldName: "defaultI8", required: false, type: Int8.self)
+ try _v.visit(field: VTOFFSET.justU8.p, fieldName: "justU8", required: false, type: UInt8.self)
+ try _v.visit(field: VTOFFSET.maybeU8.p, fieldName: "maybeU8", required: false, type: UInt8.self)
+ try _v.visit(field: VTOFFSET.defaultU8.p, fieldName: "defaultU8", required: false, type: UInt8.self)
+ try _v.visit(field: VTOFFSET.justI16.p, fieldName: "justI16", required: false, type: Int16.self)
+ try _v.visit(field: VTOFFSET.maybeI16.p, fieldName: "maybeI16", required: false, type: Int16.self)
+ try _v.visit(field: VTOFFSET.defaultI16.p, fieldName: "defaultI16", required: false, type: Int16.self)
+ try _v.visit(field: VTOFFSET.justU16.p, fieldName: "justU16", required: false, type: UInt16.self)
+ try _v.visit(field: VTOFFSET.maybeU16.p, fieldName: "maybeU16", required: false, type: UInt16.self)
+ try _v.visit(field: VTOFFSET.defaultU16.p, fieldName: "defaultU16", required: false, type: UInt16.self)
+ try _v.visit(field: VTOFFSET.justI32.p, fieldName: "justI32", required: false, type: Int32.self)
+ try _v.visit(field: VTOFFSET.maybeI32.p, fieldName: "maybeI32", required: false, type: Int32.self)
+ try _v.visit(field: VTOFFSET.defaultI32.p, fieldName: "defaultI32", required: false, type: Int32.self)
+ try _v.visit(field: VTOFFSET.justU32.p, fieldName: "justU32", required: false, type: UInt32.self)
+ try _v.visit(field: VTOFFSET.maybeU32.p, fieldName: "maybeU32", required: false, type: UInt32.self)
+ try _v.visit(field: VTOFFSET.defaultU32.p, fieldName: "defaultU32", required: false, type: UInt32.self)
+ try _v.visit(field: VTOFFSET.justI64.p, fieldName: "justI64", required: false, type: Int64.self)
+ try _v.visit(field: VTOFFSET.maybeI64.p, fieldName: "maybeI64", required: false, type: Int64.self)
+ try _v.visit(field: VTOFFSET.defaultI64.p, fieldName: "defaultI64", required: false, type: Int64.self)
+ try _v.visit(field: VTOFFSET.justU64.p, fieldName: "justU64", required: false, type: UInt64.self)
+ try _v.visit(field: VTOFFSET.maybeU64.p, fieldName: "maybeU64", required: false, type: UInt64.self)
+ try _v.visit(field: VTOFFSET.defaultU64.p, fieldName: "defaultU64", required: false, type: UInt64.self)
+ try _v.visit(field: VTOFFSET.justF32.p, fieldName: "justF32", required: false, type: Float32.self)
+ try _v.visit(field: VTOFFSET.maybeF32.p, fieldName: "maybeF32", required: false, type: Float32.self)
+ try _v.visit(field: VTOFFSET.defaultF32.p, fieldName: "defaultF32", required: false, type: Float32.self)
+ try _v.visit(field: VTOFFSET.justF64.p, fieldName: "justF64", required: false, type: Double.self)
+ try _v.visit(field: VTOFFSET.maybeF64.p, fieldName: "maybeF64", required: false, type: Double.self)
+ try _v.visit(field: VTOFFSET.defaultF64.p, fieldName: "defaultF64", required: false, type: Double.self)
+ try _v.visit(field: VTOFFSET.justBool.p, fieldName: "justBool", required: false, type: Bool.self)
+ try _v.visit(field: VTOFFSET.maybeBool.p, fieldName: "maybeBool", required: false, type: Bool.self)
+ try _v.visit(field: VTOFFSET.defaultBool.p, fieldName: "defaultBool", required: false, type: Bool.self)
+ try _v.visit(field: VTOFFSET.justEnum.p, fieldName: "justEnum", required: false, type: optional_scalars_OptionalByte.self)
+ try _v.visit(field: VTOFFSET.maybeEnum.p, fieldName: "maybeEnum", required: false, type: optional_scalars_OptionalByte.self)
+ try _v.visit(field: VTOFFSET.defaultEnum.p, fieldName: "defaultEnum", required: false, type: optional_scalars_OptionalByte.self)
+ _v.finish()
+ }
}
diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift
index 46edc512..676b0570 100644
--- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift
+++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift
@@ -4,8 +4,13 @@
import FlatBuffers
-public enum Character: UInt8, Enum {
+public enum Character: UInt8, UnionEnum {
public typealias T = UInt8
+
+ public init?(value: T) {
+ self.init(rawValue: value)
+ }
+
public static var byteSize: Int { return MemoryLayout<UInt8>.size }
public var value: UInt8 { return self.rawValue }
case none_ = 0
@@ -15,7 +20,6 @@ public enum Character: UInt8, Enum {
case bookfan = 4
case other = 5
case unused = 6
-
public static var max: Character { return .unused }
public static var min: Character { return .none_ }
@@ -52,7 +56,7 @@ public struct CharacterUnion {
}
}
}
-public struct Rapunzel: NativeStruct, NativeObject {
+public struct Rapunzel: NativeStruct, Verifiable, NativeObject {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
@@ -71,6 +75,10 @@ public struct Rapunzel: NativeStruct, NativeObject {
}
public var hairLength: Int32 { _hairLength }
+
+ public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
+ try verifier.inBuffer(position: position, of: Rapunzel.self)
+ }
}
public struct Rapunzel_Mutable: FlatBufferObject {
@@ -98,7 +106,7 @@ public struct Rapunzel_Mutable: FlatBufferObject {
}
}
-public struct BookReader: NativeStruct, NativeObject {
+public struct BookReader: NativeStruct, Verifiable, NativeObject {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
@@ -117,6 +125,10 @@ public struct BookReader: NativeStruct, NativeObject {
}
public var booksRead: Int32 { _booksRead }
+
+ public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
+ try verifier.inBuffer(position: position, of: BookReader.self)
+ }
}
public struct BookReader_Mutable: FlatBufferObject {
@@ -144,7 +156,7 @@ public struct BookReader_Mutable: FlatBufferObject {
}
}
-public struct Attacker: FlatBufferObject, ObjectAPIPacker {
+public struct Attacker: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -190,6 +202,12 @@ public struct Attacker: FlatBufferObject, ObjectAPIPacker {
Attacker.add(swordAttackDamage: obj.swordAttackDamage, &builder)
return Attacker.endAttacker(&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.swordAttackDamage.p, fieldName: "swordAttackDamage", required: false, type: Int32.self)
+ _v.finish()
+ }
}
public class AttackerT: NativeObject {
@@ -207,7 +225,7 @@ public class AttackerT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: Attacker.self) }
}
-public struct Movie: FlatBufferObject, ObjectAPIPacker {
+public struct Movie: FlatBufferObject, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_2_0_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -283,6 +301,47 @@ public struct Movie: FlatBufferObject, ObjectAPIPacker {
Movie.addVectorOf(characters: __characters, &builder)
return Movie.endMovie(&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(unionKey: VTOFFSET.mainCharacterType.p, unionField: VTOFFSET.mainCharacter.p, unionKeyName: "mainCharacterType", fieldName: "mainCharacter", required: false, completion: { (verifier, key: Character, pos) in
+ switch key {
+ case .none_:
+ break // NOTE - SWIFT doesnt support none
+ case .mulan:
+ try ForwardOffset<Attacker>.verify(&verifier, at: pos, of: Attacker.self)
+ case .rapunzel:
+ try Rapunzel.verify(&verifier, at: pos, of: Rapunzel.self)
+ case .belle:
+ try BookReader.verify(&verifier, at: pos, of: BookReader.self)
+ case .bookfan:
+ try BookReader.verify(&verifier, at: pos, of: BookReader.self)
+ case .other:
+ try ForwardOffset<String>.verify(&verifier, at: pos, of: String.self)
+ case .unused:
+ try ForwardOffset<String>.verify(&verifier, at: pos, of: String.self)
+ }
+ })
+ try _v.visitUnionVector(unionKey: VTOFFSET.charactersType.p, unionField: VTOFFSET.characters.p, unionKeyName: "charactersType", fieldName: "characters", required: false, completion: { (verifier, key: Character, pos) in
+ switch key {
+ case .none_:
+ break // NOTE - SWIFT doesnt support none
+ case .mulan:
+ try ForwardOffset<Attacker>.verify(&verifier, at: pos, of: Attacker.self)
+ case .rapunzel:
+ try Rapunzel.verify(&verifier, at: pos, of: Rapunzel.self)
+ case .belle:
+ try BookReader.verify(&verifier, at: pos, of: BookReader.self)
+ case .bookfan:
+ try BookReader.verify(&verifier, at: pos, of: BookReader.self)
+ case .other:
+ try ForwardOffset<String>.verify(&verifier, at: pos, of: String.self)
+ case .unused:
+ try ForwardOffset<String>.verify(&verifier, at: pos, of: String.self)
+ }
+ })
+ _v.finish()
+ }
}
public class MovieT: NativeObject {