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
This commit is contained in:
mustiikhalil 2021-05-14 20:59:28 +03:00 committed by GitHub
parent 04b10f5a3a
commit a5175c513a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 2291 additions and 168 deletions

1
.gitignore vendored
View File

@ -141,3 +141,4 @@ yarn-error.log
**/vendor
**/go.sum
flatbuffers.pc
**/FlatBuffers.Test.Swift.xcodeproj

View File

@ -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()
}
}

View File

@ -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();

View File

@ -2,6 +2,7 @@
# format
--indent 2
--maxwidth 80
# options
--self remove # redundantSelf

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
/// `Unpack` unpacks a flatbuffers object into a `NativeObject`
mutating func unpack() -> T
}
public protocol Enum {
associatedtype T: Scalar
static var byteSize: Int { get }
var value: T { get }
}

View File

@ -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)

View File

@ -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
}
}

View File

@ -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

View File

@ -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)

View File

@ -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))
}

View File

@ -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")
}
}

View File

@ -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

View File

@ -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))

View File

@ -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()
}
}

View File

@ -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
}
}

View File

@ -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
}
}
}

View File

@ -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
}
}

View File

@ -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))
}

View File

@ -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"]),

View File

@ -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;

View File

@ -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()
}
}

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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(

View File

@ -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) }

View File

@ -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(

View File

@ -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)
}
}

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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()
}
}

View File

@ -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 {